努力,就从现在开始。不要为逝去的的时间惋惜,也不要为未至的明天忧虑,你能把握的就只有当下的时光。
文章目录
前言
本篇为用C语言实现三子棋,用到的知识点为函数和循环,总体不难容易掌握,重点在功能实现的逻辑。那就跟随yena,一起来思考如何来实现这个小游戏吧~
提示:以下是本篇文章正文内容,下面案例可供参考
1.三子棋准备阶段
首先·,我们要建一个test.c文件,用于实现游戏的主体功能,
建一个game.c文件,存放所有函数的定义代码
最后,建一个game.h头文件,用于存放此项目所用到的所有头文件,以及函数的声明。
这个游戏总体逻辑分为以下步骤。
2.菜单打印
打印菜单,菜单的样子如下所示。先确认是否进入游戏,选择1,进入;选择0,退出;选择其他数字,则显示输入错误。此处需要用到while循环和switch语句,大家有想法了没?
答案如下
// void menu()
{
printf("*************************************\n");
printf("**** 1.开始游戏 0.退出游戏 ****\n");
printf("*************************************\n");
}
int input = 0;
do
{
menu();//打印菜单
printf("请选择是否开始游戏:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
3.游戏实现
3.1 棋盘初始化及打印
用户选择1后开始游戏,需要让用户看一下初始棋盘的样子,需要打印的棋盘如下。这个棋盘由棋子和格子构成。这里的棋子,我们要定义一个二维数组,大家观察下面的棋盘,会发现初始化的棋盘没有棋子,其实,这里的棋子被初始化为空格。棋盘的格子打印需要普通的循环,方法不唯一,能打出来即可。大家动手尝试一下吧。
答案如下。注意,此处为代码片。此函数的定义是放在game.c里
函数的声明放在game.h里
#define ROW 3
#define COL 3
这样定义棋盘的行列数,之后想改变棋盘尺寸时直接改此处即可。
char board[ROW][COL] = { 0 };
//初始化棋盘的函数
InitBoard(board, ROW, COL);
DispalyBoard(board, ROW, COL);
//棋子初始化函数定义
void InitBoard(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 DispalyBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//打印数据
//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//打印分割信息
//printf("---|---|---\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
3.2 玩家与电脑竞技
实现玩家下棋,电脑下棋,以及判断胜负的功能。玩家手动输入所选的坐标,电脑自动选择位置。有一方占满一行或一列或一条对角线,则此方胜利,若棋盘已满不分胜负,则平局。样例如下图
3.2.1 下棋实现
3.2.1.1 玩家下棋实现
玩家通过输入选择的坐标来下棋,首先要判断此时游戏是否未结束(此代码之后说明),以及此坐标大小是否合理,此坐标是否被占用,若满足以上条件,执行玩家下棋函数。玩家下的棋子用‘*’显示,,为方便用户使用,用户输入的坐标从1 1开始。
代码实现如下
// 玩家下棋函数定义
// void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
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] = '*';
break;
}
else
{
printf("坐标被占用,不能下棋,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
3.2.1.2 电脑下棋实现
电脑自动选择坐标下棋,电脑下的棋用‘#’显示。此处要用到rand()函数,rand()函数为电脑获取随机的一个大于0的整数,因为电脑选择的坐标范围是0~2,需要x=rand()%3来实现,因为任意一个整数对3取余数,就只有0,1,2的可能,那随机获取1至100呢,就是rand()%99+1啦。为保证每次选择的坐标不同,需要在主函数添加srand((unsigned int)time(NULL));代码这个代码是时间戳,保证每个时刻获取的坐标不同。这里需要<stdlib.h>以及<time.h>头文件。
具体实现如下
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;//0~2
y = rand() % col;//0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
3.3 胜负判断
若有一方一行,一列,一条对角线连成一条线,则此方胜利,若棋盘已满,但没有胜负,则平局。
3.3.1 行,列,对角线判断
代码实现如下
//行
int i = 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];//
}
}
//列
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
//对角线
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];
}
3.3.2 平局判断实现
若代码全满且无胜负之分,为平局。
代码实现如下
int IsFull(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;
}
4.附完整代码
4.1 test.c
test.c用于游戏总体逻辑实现
玩家赢,返回‘*’;电脑赢,返回‘#’;平局,返回‘Q’;
否则,游戏继续,返回‘C’。
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
printf("*****************************\n");
printf("***** 1. play 0. exit *****\n");
printf("*****************************\n");
}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘的函数
InitBoard(board, ROW, COL);
DispalyBoard(board, ROW, COL);
//下棋
while (1)
{
PlayerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DispalyBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else if(ret=='Q')
{
printf("平局\n");
}
DispalyBoard(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));//设置随机数的生成起点的
int input = 0;
do
{
menu();//打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
4.2 game.c
game.c用于存放所有代码定义,注意因为包含的头儿文件为
自定义的头文件,包含格式为#include " game.h "
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void InitBoard(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 DispalyBoard(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// for (i = 0; i < row; i++)
// {
// //打印数据
// printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
// //打印分割信息
// if(i<row-1)
// printf("---|---|---\n");
// }
//}
void DispalyBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//打印数据
//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//打印分割信息
//printf("---|---|---\n");
if (i < row - 1)
{
int j = 0;
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 x = 0;
int y = 0;
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] = '*';
break;
}
else
{
printf("坐标被占用,不能下棋,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;//0~2
y = rand() % col;//0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//满了就返回1
//不满 返回0
int IsFull(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;
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];//
}
}
//列
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
//对角线
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 (IsFull(board, row, col))
{
return 'Q';
}
//游戏继续
return 'C';
}
4.3 game.h
// A code block
var foo = 'bar';
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
//找没有下棋的随机下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
//
char IsWin(char board[ROW][COL], int row, int col);
总结
此代码需要注意的细节很多,需要大家在动手实践的过程中,细细思考,做好笔记。本篇文章到这里就终于结束啦!!!