今天我们来完成一个小案例,编写三子棋游戏。本文将会讲解三子棋的实现过程。
集成开发环境:vs2019
三子棋就是在3*3的格子中,填入○或者×,看行或列或斜对角是否是一样的图形,就判定为赢。
要完成这样一个程序,我们会在vs2019中,使用到一个头文件,一个测试文件,一个函数功能实现文件。下图game.h是头文件,game.c是游戏函数的实现文件,test.c是测试文件。
首先我们先搭建初始框架,将菜单栏先完成。
这里菜单栏模块比较简单,是通过用户输入相应数字来执行游戏的对应流程。通过switch流程分支,和输入的input来判断当前程序的状态。
int main(){
int input = 0;
int main(){
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请输入选项:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
} while(input);
return 0;
}
} while(input);
return 0;
}
在输入数字后,就要加载棋盘到控制台。
初始化棋盘我们需要用到二维数组,为了之后能够修改棋盘行和列的大小,这里没有把数字写死,而是通过在头文件定义的方式,让我们能够修改数字得到我们想要的棋盘大小。
这里是3 * 3的棋盘,后续如果用户想要n * n的棋盘也可以修改。
初始化棋盘我们要遍历数组,把数组内容重置为空格。
//初始化棋盘如下
void init_arr(char arr[ROW][COL], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
arr[i][j] = ' ';
}
}
}
重置好棋盘后,需要显示棋盘,这里以3*3的棋盘为例,我们把棋盘分别打印,先打印数据和竖线(|),如下图红圈圈出来的样子。我们先以一行为例,遍历数组先打印数据,然后打印竖线,保持一个数据一个竖线的样子,当然最后一个竖线不需要打印。
//这里的代码就是控制一行数据一行竖线的打印,整一行打印完后换行。
int i = 0;
for (i = 0; i < row; i++) {
int j = 0;
for (j = 0; j < col; j++) {
printf(" %c ", arr[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 dis_arr(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++) {
int j = 0;
for (j = 0; j < col; j++) {
printf(" %c ", arr[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");
}
}
棋盘初始化好之后,之后就要下棋,下棋分为玩家下棋和电脑下棋。
下棋就要判断两个条件:1.下棋的坐标是否合理 2.棋子下到的地方是不是空的
我们使用的是二维数组,数组下标是从0开始的,而用户并不知道这个规则,所以我们需要在用户输入的坐标基础上减去1,坐标的输入需要大于1并且在行列范围以内,输入后判断数组是否为空。
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (arr[x - 1][y - 1] == ' ')
{
arr[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,重新输入\n");
}
电脑下棋,我们采用取模的方式让坐标限制在0-2之间,这样输入的坐标就不会越界
int x = rand() % row;
int y = rand() % col;
if (arr[x][y] == ' ')
{
arr[x][y] = '#';
break;
}
上面的工作都完成后,我们可以在棋盘下棋,但还需要一个判断胜负的模块,不然格子都下满了,只能死循环了。
在玩家下棋和电脑下棋之间需要一个函数来判断胜负,我们可以定一个规则:
‘ * ’是玩家赢
‘ # ’是电脑赢
‘Q’ 是平局
‘C’ 是继续游戏
while (1)
{
ret = is_win(arr, ROW, COL);
if (ret != 'C')
break; //如果ret不等于C就会跳出循环,这时候只会有输赢和平局三种结果
computer_move(arr, ROW, COL);
dis_arr(arr, ROW, COL);
ret = is_win(arr, ROW, COL);
if (ret != 'C')
break; //如果ret不等于C就会跳出循环,这时候只会有输赢和平局三种结果
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
}
//让ret返回当前胜负状态
char ret = is_win(arr, ROW, COL);
char is_win(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ') //判断一行是否相等
{
return arr[i][0];
}
}
for (i = 0; i < col; i++)
{
if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ') //判断一列是否相等
{
return arr[0][i];
}
}
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ') //判断斜对角是否相等
{
return arr[1][1];
}
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ') //判断斜对角是否相等
{
return arr[1][1];
}
//判断平局
if (is_full(arr, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
完整代码:
//game.h
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define COL 3
#include
//初始化棋盘
void init_board(char arr[ROW][COL], int row, int col);
//玩家移动棋子
void player_move(char arr[ROW][COL], int row, int col);
//棋盘展示
void dis_board(char arr[ROW][COL], int row, int col);
//电脑移动棋子
void computer_move(char arr[ROW][COL], int row, int col);
//判断游戏状态
char is_win(char board[ROW][COL], int row, int col);
//game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_arr(char arr[ROW][COL], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
arr[i][j] = ' ';
}
}
}
void dis_arr(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++) {
int j = 0;
for (j = 0; j < col; j++) {
printf(" %c ", arr[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 player_move(char arr[ROW][COL],int row,int col) {
int x = 0;
int y = 0;
printf("玩家下棋\n");
while (1)
{
printf("请输入要下棋的坐标:>");
scanf("%d %d", &x, &y);
//1.坐标的合法性
//2.坐标是否被占用
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (arr[x - 1][y - 1] == ' ')
{
arr[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,重新输入\n");
}
}
}
void computer_move(char arr[ROW][COL], int row, int col) {
printf("电脑下棋\n");
while (1) {
int x = rand() % row;
int y = rand() % col;
if (arr[x][y] == ' ')
{
arr[x][y] = '#';
break;
}
}
}
static int is_full(char arr[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 (' ' == arr[i][j])
{
return 0;
}
}
}
return 1;
}
char is_win(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
{
return arr[i][0];
}
}
for (i = 0; i < col; i++)
{
if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
{
return arr[0][i];
}
}
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
{
return arr[1][1];
}
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')
{
return arr[1][1];
}
//判断平局
if (is_full(arr, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include "game.h"
void menu() {
printf("*********三子棋游戏********\n");
printf("*********1.开始游戏******\n");
printf("*********0.退出游戏******\n");
}
void game()
{
printf("游戏开始\n");
char ret = 0;
//数据的存储需要一个3*3的二维数组
char arr[ROW][COL] = { 0 };
init_arr(arr, ROW, COL);
dis_arr(arr, ROW, COL);
//玩游戏
while (1)
{
player_move(arr, ROW, COL);
dis_arr(arr, ROW, COL);
ret = is_win(arr, ROW, COL);
if (ret != 'C')
break;
computer_move(arr, ROW, COL);
dis_arr(arr, ROW, COL);
ret = is_win(arr, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else if (ret == 'Q')
{
printf("平局\n");
}
dis_arr(arr, ROW, COL);
}
int main(){
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请输入选项:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
} while(input);
return 0;
}