- 率先完成三子就是胜利!
- 具体实现、功能函数定义、函数声明分别放在了三个文件中。
- 从main函数入口开始。
- 啥也也不说了,都在代码里了
运行截图:
一个运行结果:
函数声明在game.h文件
#pragma once
//函数声明
//游戏逻辑
/* 1. 玩家选择 2. 创建数组,打印棋盘 3. 用户下棋,电脑下棋 4. 判断输赢,输出结果 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3 //棋盘(字符数组)的行
#define COLUMN 3 //棋盘(字符数组)的列
//初始化棋盘
void initboard(char board[ROW][COLUMN], int row, int column);
//菜单
void menu();
//打印棋盘
void Print_board(char board[ROW][COLUMN], int row, int column);
//玩家输入
void keyboard_player(char board[ROW][COLUMN],int row, int column);
//电脑输入
void keyboard_pc(char board[ROW][COLUMN],int row, int column);
判断给定坐标是否是空格或电脑的棋
//int iswhat(char board[ROW][COLUMN], int x, int y);
//判断状态
/* 玩家赢 * 电脑赢 # 平局 Draw 继续 Continue */
char ISWIN(char board[ROW][COLUMN], int row, int column);
//判断棋盘是否有空格
int isfull(char board[ROW][COLUMN], int row, int column);
具体实现在game.c文件
#include "game.h"
void game() {
//创建棋盘,大小可以自己定义
char board[ROW][COLUMN] = {
0 };
//初始化棋盘
initboard(board, ROW, COLUMN);
//简单随机,确定谁是欧皇,1是玩家,0是电脑
unsigned int ret = rand() % 2;
if (ret == 1) {
printf("玩家先手!\n");
//游戏中玩家和电脑交替下棋,是一个循环
do {
//玩家输入
keyboard_player(board, ROW, COLUMN);
//实时打印棋盘和棋子
Print_board(board, ROW, COLUMN);
//判断棋局的状态
if (ISWIN(board, ROW, COLUMN) != 'C') {
break;
}
//电脑输入
keyboard_pc(board, ROW, COLUMN);
//实时打印棋盘和棋子
Print_board(board, ROW, COLUMN);
//判断棋局的状态
if (ISWIN(board, ROW, COLUMN) != 'C') {
break;
}
} while (1);
}
else {
printf("电脑先手!\n");
//游戏中玩家和电脑交替下棋,是一个循环
do {
//电脑输入
keyboard_pc(board, ROW, COLUMN);
//实时打印棋盘和棋子
Print_board(board, ROW, COLUMN);
//判断棋局的状态
if (ISWIN(board, ROW, COLUMN) != 'C') {
break;
}
//玩家输入
keyboard_player(board, ROW, COLUMN);
//实时打印棋盘和棋子
Print_board(board, ROW, COLUMN);
//判断棋局的状态
if (ISWIN(board, ROW, COLUMN) != 'C') {
break;
}
} while (1);
}
//跳出循环时,棋局一定是有结果了,所以要检索ISWIN函数的返回值确定结果
if (ISWIN(board, ROW, COLUMN) == '*') {
printf("永远滴神!\n");
}
else if (ISWIN(board, ROW, COLUMN) == '#') {
printf("末日人机了!\n");
}
else {
printf("旗鼓相当的对手!\n");
}
}
int main() {
//用于玩家输入的变量
int input = -1;
//随机数种子,用于电脑的随机下棋坐标生成
srand((unsigned)time(NULL));
char ch;
//一个循环,向玩家展示菜单,玩家输入选择决定循环的进行
do {
//菜单
menu();
printf("请输入选择>");
scanf("%d", &input);
//这个循环用来弥补scanf接受字符数据时会死循环的问题
while ((ch = getchar()) != '\n') {
//这是一条空语句
;
}
switch (input) {
case 1:
//开始游戏
game();
break;
case 0:
printf("游戏退出\n");
break;
default:
printf("选择错误,请重新输入\n");
break;
}
//只有当input是0时循环才结束
} while (input);
return 0;
}
函数定义,在gamefuntion.c文件
//函数定义
#include "game.h"
//初始化棋盘
void initboard(char board[ROW][COLUMN], int row, int column) {
int i = 0;
for (i = 0; i < ROW; i++) {
int j = 0;
for (j = 0; j < COLUMN; j++) {
board[i][j] = ' ';
}
}
}
//菜单
void menu() {
printf("***************************\n");
printf("****** 1.三子棋 ******\n");
printf("****** 0.退出 ******\n");
printf("***************************\n");
}
//打印棋盘
void Print_board(char board[ROW][COLUMN], int row, int column) {
int i = 0;
int j = 0;
for (i = 0; i < row; i++) {
//棋盘列标
if (i == 0) {
//棋盘左上角用四个空格填充
printf(" ");
//列标与棋盘的棋子对齐,考虑到棋盘可能增大到两位数,加一点格式输出
for (j = 0; j < column; j++) {
printf(" %-2d ", j + 1);
}
printf("\n");
}
//棋盘行标与棋子对齐,与列标相似。在每一行只打印一次
for (j = 0; j < column; j++) {
if (j == 0) {
printf(" %-2d ", i + 1);
}
printf(" %c ", board[i][j]);
if (j < column - 1)
printf("|");
}
printf("\n");
if (i < row - 1) {
//棋盘行标相关的四个空格,只在每行的开始打印
for (j = 0; j < column; j++) {
if (j == 0) {
printf(" ");
}
printf("---");
if (j < column - 1)
printf("|");
}
}
printf("\n");
}
}
//玩家输入
void keyboard_player(char board[ROW][COLUMN],int row, int column) {
printf("请输入三子棋的坐标>");
int x, y;
char ch;
while (1) {
scanf("%d%d", &x, &y);
while ((ch = getchar()) != '\n') {
;
}
if (x >= 1 && x <= row && y >=1 && y <= column) {
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else {
printf("转牛角尖是吧!\n请重新输入>");
}
}
else {
printf("输入无效!\n请重新输入>");
}
}
printf("玩家下棋:\n");
}
//电脑输入
void keyboard_pc(char board[ROW][COLUMN], int row, int column) {
printf("电脑下棋:\n");
int x, y;
while (1) {
x = rand() % row;
y = rand() % column;
if (board[x][y] == ' ') {
board[x][y] = '#';
break;
鸡肋的电脑下棋判定
判断周围平行的四个
//if (x + 1 < ROW && y < COLUMN && iswhat(board, x + 1, y)) {
// board[x][y] = '#';
// break;
//}
//if (x - 1 < ROW && y < COLUMN && iswhat(board, x - 1, y)) {
// board[x][y] = '#';
// break;
//}
//if (x < ROW && y + 1 < COLUMN && iswhat(board, x, y + 1)) {
// board[x][y] = '#';
// break;
//}
//if (x < ROW && y - 1 < COLUMN && iswhat(board, x, y - 1)) {
// board[x][y] = '#';
// break;
//}
判断周围对角的四个
//if (x + 1 < ROW && y + 1< COLUMN && iswhat(board, x + 1, y + 1)) {
// board[x][y] = '#';
// break;
//}
//if (x - 1 < ROW && y - 1 < COLUMN && iswhat(board, x - 1, y - 1)) {
// board[x][y] = '#';
// break;
//}
//if (x + 1 < ROW && y - 1 < COLUMN && iswhat(board, x + 1, y - 1)) {
// board[x][y] = '#';
// break;
//}
//if (x - 1 < ROW && y + 1 < COLUMN && iswhat(board, x - 1, y + 1)) {
// board[x][y] = '#';
// break;
//}
}
}
}
判断给定坐标是否是空格或电脑的棋,是返回1,否则返回0
//int iswhat(char board[ROW][COLUMN], int x, int y) {
// if (board[x][y] == ' ' || board[x][y] == '#') {
// return 1;
// }
// else {
// return 0;
// }
//}
//判断状态
/* 玩家赢 * 电脑赢 # 平局 Draw 继续 Continue */
//只判断三子棋下的输赢情况,棋盘增大时、五子棋时此判断方法无效
char ISWIN(char board[ROW][COLUMN], int row, int column) {
int i = 0;
//玩家赢 * 电脑赢 #
//每行和每列
for (i = 0; i < ROW; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') {
return board[i][0];
}
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ') {
return board[0][i];
}
}
//主对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ') {
return board[0][0];
}
//副对角线
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != ' ') {
return board[2][0];
}
//平局
if (isfull(board, row, column)) {
return 'D';
}
//继续
return 'C';
}
//返回1是满了
//返回0是未满
int isfull(char board[ROW][COLUMN], int row, int column) {
int flag = 1;
int i = 0;
for (i = 0; i < ROW; i++) {
int j = 0;
for (j = 0; j < COLUMN; j++) {
if (board[i][j] == ' ') {
flag = 0;
break;
}
}
}
return flag;
}
尝试打印多行多列棋盘:
10行15列:
END