使用C语言编写三子棋:
一、制作整个游戏的框架
首先我们要先编写出整个游戏的框架,也就是要先有游戏菜单并且要能够实现菜单的功能,代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{
printf("*************************\n");
printf("***** 1. play ******\n");
printf("***** 0. exit ******\n");
printf("*************************\n");
}
void Playgame()
{
printf("三子棋\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
Playgame();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
通过switch语句可以让用户选择菜单的功能若输入1,则会进入Playgame函数屏幕会打印出“三子棋”,而进入到循环的条件判断部分时,input为1,游戏可以重新开始;若输入0,则循环条件为假,”退出游戏“并且程序终止,若既不是1也不是0,循环条件同样为真,用户需要重新需要重新选择。
二、初始化并展现空棋盘
1.初始化棋盘
游戏的基本框架构建完成后,接下来就是完善Playgame函数,该函数也是游戏的核心。首先我们要给用户呈现一个3x3的棋盘,不难想到要使用二维数组,这里我们定义一个init_board()函数先初始化棋盘,
#define ROW 3
#define COL 3
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0;//行
int j = 0;//列
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void Playgame()
{
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
}
注意:这里为方便观察代码,只展现代码的一部分
2.展现空棋盘
#define ROW 3 和 #define COL 3 是为了方便未来如果需要不是3x3棋盘时更改数据更方便。可以看出这里将棋盘全部初始化为空格,这里只是初始化棋盘,还要为用户展现出棋盘的模样,但如果值单纯的打印初始化后的棋盘,用户看到的只是一片空白,所以要定义一个display_board()函数来完善棋盘。代码如下:
void display_board(char board[ROW][COL], int row, int col)
{
int i = 0;//行
int j = 0;//列
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
{
printf("---");
}
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void Playgame()
{
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
//展现空棋盘
display_board(board, ROW, COL);
}
至此,整个代码可以为用户呈现出整个棋盘,如图:
三、玩家下棋和电脑下棋
棋盘完成后,当然就要开始下棋喽,这里我们分别定义Playermove() 和 Computermove() 两个函数来编表示玩家下棋和电脑下棋
1.玩家下棋
void Playermove(char board[ROW][COL], int row, int col)
{
int i = 0;//玩家输入的行
int j = 0;//玩家输入的列
while (1)
{
printf("玩家下棋,请输入坐标:");
scanf("%d %d", &i, &j);
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '*';
break;
}
else
{
printf("输入错误,请重新输入:\n");
}
}
void Playgame()
{
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
display_board(board, ROW, COL);
Playermove(board, ROW, COL);
display_board(board, ROW, COL);//玩家每下完一步棋,就展示依次下完后的棋盘
}
我们知道数组的下标是从0开始的,但我们总不能指望玩家都是程序员,所以我们要将玩家输入的坐标分别减1,如果玩家输入的坐标的位置是空格,则将该位置赋值为 * 并终止循环,若玩家输入坐标的位置不是空格,则循环继续,玩家需重新输入坐标。
2.电脑下棋
void Computermove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
void Playgame()
{
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
display_board(board, ROW, COL);
Playermove(board, ROW, COL);
display_board(board, ROW, COL);
Computermove(board, ROW, COL);
display_board(board, ROW, COL);//电脑每下完一步就展示一次棋盘
}
这里还要在主函数的一开始加上这行代码 srand((unsigned int)time(NULL));这行代码是用来初始化随机数生成器的。srand函数需要传入一个unsigned int类型的参数作为种子,一般使用当前时间作为种子,可以保证每次运行程序时生成的随机数序列都是不同的。time(NULL)函数返回的是当前系统时间的秒数,因为时间在不断地变化,所以不同的时戳会对应不同的随机数序列。而 x = rand() % row; y = rand() % col; 是用来生成一个介于0到2之间的随机数的。rand()函数会生成一个大于等于0且小于等于RAND_MAX的随机整数,RAND_MAX是C语言标准库中的常量,表示由rand()函数生成的随机数的最大值,而%3的操作会将这个随机整数对3取模,得到的结果就是0、1、2之中的一个,因此x和y的值就是随机的0、1、2之中的一个。当x和y确定后,Computermove函数中如果坐标(x,y)处为空,则将其赋值为#。
四、判断结果
一盘棋的结果有,玩家获胜、电脑获胜、平局和继续下棋,所以我们定义一个isWin(),
int isFair(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char isWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//判断电脑赢还是玩家赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][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 (isFair(board, row, col))
{
return 'Q';
}
//以上结果都不是则棋局继续
return 'C';
}
无论是玩家赢还是电脑赢,在某一横线、竖线和斜线上肯定都是*或#,则我们将其返回至Playgame函数中若为平局,则返回Q,以上结果都不是则返回C,利用这些返回值,我们要在Play game函数中做文章。
void Playgame()
{
char ret = 0;
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
display_board(board, ROW, COL);
while (1)
{
Playermove(board, ROW, COL);
display_board(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
Computermove(board, ROW, COL);
display_board(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家获胜!\n");
}
else if (ret == '#')
{
printf("电脑获胜!\n");
}
else if (ret == 'Q')
{
printf("平局!\n");
}
}
因为整盘棋中,玩家和电脑不可能只下一步棋,所以要在Playgeme函数中加一个while循环直到分出胜负,或平局循环终止。isWin()的返回值有ret接收,当ret不是C时循环终止,然后根据ret是什么来判断结果是什么。
五、完整代码展现
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<time.h>
#define ROW 3
#define COL 3
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0;//行
int j = 0;//列
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void display_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
{
printf("---");
}
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void Playermove(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
while (1)
{
printf("玩家下棋,请输入坐标:");
scanf("%d %d", &i, &j);
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '*';
break;
}
else
{
printf("输入错误,请重新输入:\n");
}
}
}
void Computermove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int isFair(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char isWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][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 (isFair(board, row, col))
{
return 'Q';
}
return 'C';
}
void menu()
{
printf("*************************\n");
printf("***** 1. play ******\n");
printf("***** 0. exit ******\n");
printf("*************************\n");
}
void Playgame()
{
char ret = 0;
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
display_board(board, ROW, COL);
while (1)
{
Playermove(board, ROW, COL);
display_board(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
Computermove(board, ROW, COL);
display_board(board, ROW, COL);
ret = isWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家获胜!\n");
}
else if (ret == '#')
{
printf("电脑获胜!\n");
}
else if (ret == 'Q')
{
printf("平局!\n");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
Playgame();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
具体的运行,大家可以自行去尝试,那么谢谢大家阅读!