文章目录
一 需求分析
我们需要建3个文件来实现三子棋游戏:1.test.c文件是用来测试代码的;2.game.h文件是函数的声明;3.game.c是函数的实现.具体的内容会在实现步骤里面写.
整个代码的逻辑其实就是:
1.需求分析;
2.需求的实现;
3.调试和运行;
需求分析:1.打印菜单的逻辑; 2.初始化棋盘的内容为空; 3.对棋盘的打印; 4.玩家下棋;5.电脑下棋; 6.判断输赢
只要这个分析好了 ,代码的实现就容易很多.
需求的实现:根据上面的分析,写出每个分析用函数封装起来,然后在函数里面实现,需要用的时候直接调用就好了.
调试和运行:在写代码时,需要我们写一点代码就运行和调试,这样就可以快速找到和解决问题了.
这就是整个代码实现的逻辑啦
二 实现步骤
2.1菜单的打印
为了使主函数main里面的内容简单点,我们写一个函数来实现菜单打印的逻辑;
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("***********************************************\n");
printf("********** 1. play *********\n");
printf("********** 0. exit *********\n");
printf("***********************************************\n");
}
void test()
{
printf("请选择->\n");
menu();
int input = 0;
do
{
scanf("%d", &input);
switch (input)
{
case 1:
//game()函数;玩游戏的实现
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
这就完成了整个菜单逻辑的打印了,实现起来很简单
2.2初始化棋盘内容
现在进入了整个三子棋游戏部分的实现,我们把游戏实现部分用一个game();函数封装起来,首先是实现初始化棋盘内容,把玩三子棋看作是一个字符型的二维数组,我们需要用一个三行三列的二维数组的形式把他存起来.
我们是写了一个init_board( );函数来实现这个功能,这个函数在game.h文件里面声明,在这个game();函数中调用
//初始化棋盘内容函数的实现
void init_board(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++)
{
board[i][j] = ' ';
}
}
}
2.3棋盘的打印
可以根据自己喜欢的样子打印棋盘,我们写了一个print_board( );函数来实现这个功能,这个函数在game.h文件里面声明,在这个game();函数中调用
//打印棋盘内容函数的实现
void print_board(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++)
{
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");
}
}
}
棋盘打印出来的样子
2.4玩家下棋
玩家输入对应的x,y坐标,来确定下棋的位置,如果坐标为空则输入’*'代表玩家的落子位置,玩家下棋这个过程是一个循环,直到平局或者玩家赢或者电脑赢才结束.
我们是写了一个player_move( );这个函数来实现玩家下棋的功能,这个函数在game.h文件中声明,在game( );函数中调用.
//玩家下棋函数的实现
player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋\n");
while (1)
{
int x = 0;
int y = 0;
printf("请输入对应的坐标\n");
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] = '*';
break;
}
else
{
printf("该坐标被占用\n");
}
}
else
{
printf("该坐标非法\n");
}
}
}
2.5电脑下棋
电脑下棋我们需要生成随机坐标,需要用到rand()函数来实现,使用rand函数前需要使用sand()函数,srand又需要时间戳来产生随机种子,头文件的包含有#include<stdlib.h>和#include<time.h>
电脑输入对应的x,y坐标,来确定下棋的位置,如果坐标为空则输入’#'代表电脑的落子位置,电脑下棋这个过程是一个循环,直到平局或者玩家赢或者电脑赢才结束.
我们是写了一个computer_move( );这个函数来实现电脑下棋的功能,这个函数在game.h文件中声明,在game( );函数中调用.
//电脑下棋
//在test();函数中使用了srand函数,不然rand生成的随机数每次开始玩游戏都是一样的坐标
void computer_move(char board[ROW][COL], int row, int col)
{
int x = rand() % row;
int y = rand()% col;
printf("电脑下棋");
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
2.6判断输赢
我们写了一个is_win函数来判断是玩家赢,还是电脑赢, 平局返回Q,继续返回C
玩家赢返回’*’
电脑赢返回’#’
平局返回’Q’
继续返回’C’
//判断是否平局,棋盘满了还没有返回则是平局,返回字母Q
static int is_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;
}
}
}
return 1;
}
//判断输赢
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][0];
}
}
//判断列是否相等
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 (is_full(board, row, col)==1)
{
return 'Q';
}
return 'C';
}
玩家赢:
平局:
电脑赢:
下面三个文件就是三子棋游戏的代码
2.7 test.c文件的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("***********************************************\n");
printf("********** 1. play *********\n");
printf("********** 0. exit *********\n");
printf("***********************************************\n");
}
void game()
{
char ret = 0;//用来接收后面对输 赢 平局还是继续的返回字符
char board[ROW][COL];//ROW COL在game.h中宏定义为3
init_board(board, ROW, COL);
print_board(board, ROW, COL);
while (1)
{
player_move(board, ROW, COL);
print_board(board, ROW, COL);//落子后打印
//判断是否赢
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
computer_move(board, ROW, COL);
print_board(board, ROW, COL);//落子后打印
//判断是否赢
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
printf("请选择->\n");
menu();
scanf("%d", &input);
switch (input)
{
case 1:
//game()函数;玩游戏的实现
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
2.8 game.c文件的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘内容函数的实现
void init_board(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++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘内容函数的实现
void print_board(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++)
{
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 player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋\n");
while (1)
{
int x = 0;
int y = 0;
printf("请输入对应的坐标\n");
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] = '*';
break;
}
else
{
printf("该坐标被占用\n");
}
}
else
{
printf("该坐标非法\n");
}
}
}
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判断是否平局,棋盘满了还没有返回则是平局,返回字母Q
static int is_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;
}
}
}
return 1;
}
//判断输赢
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][0];
}
}
//判断列是否相等
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 (is_full(board, row, col)==1)
{
return 'Q';
}
return 'C';
}
2.9 game.h文件的代码
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
//初始化棋盘内容的函数声明
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘的内容函数声明
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋的函数声明
void player_move(char board[ROW][COL], int row, int col);
//电脑下棋函数的声明
void computer_move(char board[ROW][COL], int row, int col);
//判断输赢的函数声明
char is_win(char board[ROW][COL], int row, int col);
三 总结
整个代码的逻辑其实就是:
1.需求分析;
2.需求的实现;
3.调试和运行
需求分析:1.打印菜单的逻辑; 2.初始化棋盘的内容为空; 3.对棋盘的打印; 4.玩家下棋;5.电脑下棋; 6.判断输赢
只要这个分析好了 ,代码的实现就容易很多.
需求的实现:根据上面的分析,写出每个分析用函数封装起来,然后在函数里面实现,需要用的时候直接调用就好了.
调试和运行: 在写代码时,需要我们写一点代码就运行和调试,这样就可以快速找到和解决问题了.
这就是整个代码实现的逻辑啦
注意:
1.在设定行和列的时候我们可以用#define来定义,如果要修改行和列的话 就可以直接在#define定义里面修改;
2.使用随机坐标时,要用到随机值,rand函数可以生成随机值,但是每次程序开始运行时,都是一样的值,所以在使用rand函数前要使用srand函数,srand函数使用时,需要一个随时变化的值,那么这个值可以是时间戳,需要使用time这个函数;
完结~