对于井字棋游戏大家一定都不陌生吧,它是一个简单的休闲游戏,那么我们怎么用C语言实现这款游戏呢?让我们一起来完成它:
游戏的流程
玩家根据菜单提示选择进入游戏或者退出游戏;
玩家进入游戏以后按顺序与电脑下棋
根据下棋结果判断输赢或是平局
一、创建菜单及选择开始游戏
菜单可根据自己的需求建一个无返回值的菜单函数实现对菜单的打印
void menu()
{
printf("*********选择:1 -->开始游戏\n");
printf("*********选择:0 -->退出游戏\n");
}
菜单创建之后,我们选择开关语句switch来进入游戏,选1开始,选0退出,选错重选
int input;
do
{
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择:");
break;
}
} while (input);
game函数即游戏流程
二、game函数的实现
1.棋盘的创建及初始化
井字棋棋盘其实可以抽象化为三行三列的二维数组,即char board[ROW][COL],ROW为行,COL(原形column)为列,并对其初始化(这里我们将数组的每个值都初始化为空格(' '),以达到棋盘为空的效果),初始化用我们自定义的 initboard()函数
void initboard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
2.棋盘的打印
为了实现“#”形的棋盘,我们对棋盘进行编辑然后打印
void printboard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
得到如下的效果:
3.玩家与电脑对弈
我们让玩家先下棋,然后让电脑在空位随机下棋,每次下完后都对棋盘进行打印,方便我们观察游戏的过程。
玩家下棋(棋子是“R”)我们用playerboard()实现,我们定义x与y组成坐标让玩家选择坐标,这里我们需要注意的是如果是一个不了解数组或者是程序的玩家,往往会把[1][1]认作最小的坐标,而在数组中,数组下标的最小值是0,也就是以[0][0]开头,所以我们在编写程序时需要注意在判断坐标是否合法的过程中对玩家输入的坐标的值减1,以得达到正确的判断结果,代码如下:
void playerboard(char board[ROW][COL], int row, int col)
{
int x, y;
printf("玩家下棋\n");
while(1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'R';
break;
}
else
{
printf("坐标非法,请重新输入:");
}
}
}
}
在玩家下完棋之后对棋盘进行打印:
紧接着是电脑下棋(棋子是“L”),电脑随机下棋就需要用到rand()函数,而rand()函数使用前又需要使用srand()函数,在C语言实现猜数字游戏中有提过,所以这里的细节略过。代码如下:
void computerboard(char board[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
int x, y;
srand((unsigned int)time(0));
while(1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = 'L';
break;
}
}
}
4.游戏输赢的判断
下棋肯定不止一回合,所以我们采用循环的方式,将玩家下棋与电脑下棋放在一个循环当中,并且用一个判断输赢的函数将函数的返回值赋予新定义的一个变量ret,根据给ret返回的值(这里采用的是返回“R”或“L”)来判断谁胜谁负,代码如下:
while (1)
{
playerboard(board, ROW, COL);
printboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
computerboard(board, ROW, COL);
printboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == 'R')
printf("玩家赢\n");
else if (ret == 'L')
printf("电脑赢\n");
else
printf("平局\n");
}
而判断输赢的函数is_win()的代码也如图所示:
char is_win(char board[ROW][COL], int row, int col)
{
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][1];
}
}
//判断列
for (i = 0; i < col; i++)
{
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[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局
if (if_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
if_full()函数是服务于is_win(),是判断棋盘是否填满的函数,代码是:
//判断是否填满
static int if_full(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;//没满
break;
}
}
}
return 1;//满了
}
总结
写井字棋游戏对我们的函数调用,数组使用,宏定义的使用以及循环、判断和选择语句等都有很大的提升与见解,对我们的思维也有很不错的提高
代码
game.h
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
//菜单
void menu();
//游戏
void game();
//初始化棋盘
void initboard(char board[ROW][COL], int row, int col);
//打印棋盘
void printboard(char board[ROW][COL], int row, int col);
//玩家下棋;
void playerboard(char board[ROW][COL], int row, int col);
//电脑下棋
void computerboard(char board[ROW][COL], int row, int col);
//判断输赢
char is_win(char board[ROW][COL], int row, int col);
//判断是否空
static int if_full(char board[ROW][COL], int row, int col);
game.c
#include "game.h"
//初始化
void initboard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印
void printboard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
//玩家
void playerboard(char board[ROW][COL], int row, int col)
{
int x, y;
printf("玩家下棋\n");
while(1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'R';
break;
}
else
{
printf("坐标非法,请重新输入:");
}
}
}
}
//电脑
void computerboard(char board[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
int x, y;
srand((unsigned int)time(0));
while(1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = 'L';
break;
}
}
}
//判断
char is_win(char board[ROW][COL], int row, int col)
{
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][1];
}
}
//判断列
for (i = 0; i < col; i++)
{
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[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局
if (if_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
//判断是否填满
static int if_full(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;//没满
break;
}
}
}
return 1;//满了
}
test.c
#include "game.h"
void menu()
{
printf("*********选择:1 -->开始游戏\n");
printf("*********选择:0 -->退出游戏\n");
}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
printf("游戏开始\n");
initboard(board, ROW, COL);
printboard(board, ROW, COL);
while (1)
{
playerboard(board, ROW, COL);
printboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
computerboard(board, ROW, COL);
printboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == 'R')
printf("玩家赢\n");
else if (ret == 'L')
printf("电脑赢\n");
else
printf("平局\n");
}
void test()
{
menu();
printf("请输入:>");
int input;
do
{
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择:");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
PS:Visual Stdio 2022