栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

【数组实现三字棋小游戏】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【数组实现三字棋小游戏】

这里写目录标题
    • 思路分析
      • 文件存放
      • 思路流程
    • 代码实现
      • 菜单界面代码
      • 游戏代码的实现
        • InitBoard 函数
        • DispalyBoard 函数
        • 玩家下棋
        • 电脑下棋
        • 判断输赢
          • 是否平局
      • game函数调用游戏函数
      • 函数的声明
    • 所有代码
      • game.h
      • game.c
      • test.c

数组在以后的编程生涯中我们会与他打无数交道,所以我们必须把他牢牢的掌握住,今天我们来学习个三字棋项目,来加强对数组的运用。
因为本人技术较菜,也是博客新手,所以有写地方表达得不是很到位,请各位大佬评论区多多指教

思路分析 文件存放

在该项目当中,首先我们要分析应该用什么文件存放什么功能的代码:
1.我们分析得出要用 test.c 来测试游戏逻辑是否正确,main函数写在 test.c 中。
2.用 game.c 来对游戏中功能代码的实现。
3.用 game.h 来存放游戏代码函数的声明,库函数的声明,宏常量的定义。

思路流程

1.该项目我们首先要写出一个菜单界面来显示逻辑选项,我们要通过不同的选项写不同的代码。可以分为进入游戏,退出游戏两大版块。
2.我们通过菜单界面选择进入游戏后,应该编写一个游戏的函数。我们的三字棋棋盘界面应该长这样子的:

应该用一个二维数组来实现该棋盘。
3.有了棋盘后,我们就应该写一个玩家下棋的代码,实现玩家下棋,还要写出一个下棋后打印的代码,实现下棋后可以打印在屏幕上的功能。
4.然后我们还要写一个电脑下棋的代码,因为本人技术有限,所以只能写出电脑随机下棋的笨代码。
5.最后我们还要对下棋后的棋局进行判断,判断是否有一方胜利或者平局亦或者还没有决出胜负,并进行相应的处理。
思路理清楚了,接下来就让我们一步一步来实现这一个三字棋项目。

代码实现 菜单界面代码

我们先写出自己喜欢的菜单界面函数 menu,将写好的代码放在main函数里头,因为我们不只想玩一局游戏,所以将 menu 放进 do { } while 循环里面。并用switch语句来对逻辑的判断,定义一个变量 input 来作为 switch 语句的判断常量,并且 input 也可以用作while 循环的判断成分,因为 我们在 meun 函数中设置 0 为退出游戏,是为了后面只定义一个变量input ,巧妙的作为循环判断与 switch 语句的判断。

void menu() {
	printf("******************************n");
	printf("********** 1 . play **********n");
	printf("********** 0 . exit **********n");//选择 0 退出是为了后面只定义一个变量input ,可以作为循环判断与switch
	printf("******************************n");
}
int main() {
	int input = 0;
	do {
		menu();//菜单
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
			case 0:
				printf("退出游戏成功n");
				break;
			case 1:
				break;
			default:
				printf("输入错误n");
		}
	} while (input);
	return 0;
} 
游戏代码的实现

当我们在菜单界面中选择 1 进入游戏后,这个时候就要写一个 游戏函数 game 来补充逻辑,
进入 game 函数后,我选择了用二维数组来存放该棋盘 ,创建数组后,就要对该数组进行初始化并把棋盘打印出来,用 InitBoard 函数来对数组初始化,DispalyBoard 函数来打印数组。
并且因为二维数组的行和列在该项目中会广泛用到,所以我们将他定为宏常量,存放在 game.h 中。

void game() {
	char board[ROW][COL] = { 0 };
	//棋盘初始化
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
}
InitBoard 函数

InitBoard 函数是属于来实现游戏功能的代码,所以我打算将他写在 play.c 文件中,
我选择用 ‘空格’ 来实现对数组的初始化,用嵌套for循环的方式将 ‘空格’ 存入数组中,

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] = ' ';
		}
	}
}
DispalyBoard 函数

我将要在 DispalyBoard 函数中打印出棋盘的形状 ,预览图如下:

分析得,我可以把这个棋盘分为三个部分,一个部分包含三个空格两条竖线,加上分割线,最后一部分不需要分割线。
所以写得代码如下:

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");														
		if (i < row - 1) {
			//printf("---|---|---n");
			int j = 0;
			for (j = 0; j < col; j++) {
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("n");
		}
	}
}
玩家下棋

数组初始化与棋盘打印完后,我们就要来考虑怎么让玩家下棋的代码了。将代码写在PlayMove函数内,
先让玩家输入想下的棋子的位置,再用一个for循环来判断,该位置是否为 ‘空格’ ,如果为 ‘空格’ 表示该位置已经有人落子了不可以再落到该位置,所以要重新输入位置,所以把判断存放在 while 循环中。如果该位置不为 ‘空格’ 就落子到该位置,如果玩家输入的坐标超出棋盘的范围,就提升输入错误重新输入 。我规定玩家的棋子用 ‘*’ 来表示。

void PlayMove(char board[ROW][COL], int row, int col) {
	int i = 0;
	int j = 0;
	while (1) {
		printf("玩家请输入:>n");
		printf("请输入坐标:>");
		scanf("%d %d", &i, &j);
		if (i <= ROW && i > 0 && j <= COL && j > 0) {
			if (board[i - 1][j - 1] == ' ') {
				board[i - 1][j - 1] = '*';
				break;
			}
			else {
				printf("坐标被占用不能下该位置,请选择其他位置n");
				printf("n");
			}
		}
		else {
			printf("坐标非法请重新输入n");
		}
		printf("n");
	}
}

在玩家下棋后,我们要顺便用 DispalyBoard 函数棋与棋盘打印出来,在继续考虑电脑下棋的代码。

电脑下棋

电脑下棋我们可以写个低配版,让电脑随机下棋,不考虑算法在内。用到 rand()函数 ,电脑生成随机数,然后需要在main函数设定随机数起点,srand((unsigned int)time(NULL));//设置生成随机数的起点。将生成的随机数模上 行和列 就会生成在 0 ~ 2 之内的随机数。下棋的判断与玩家一致。

void ComputerMove(char board[ROW][COL], int row, int col) {
	printf("电脑下棋:>n");
	int i = 0;
	int j = 0;
	while (1) {
		i = rand() % row;//0 ~ 2
		j = rand() % col;//0 ~ 2
		if (board[i][j] == ' ') {
			board[i][j] = '#';
			break;
		}
	}

}
判断输赢

在玩家和电脑都下棋后,我们需要对这时候的棋局进行判断,看是否有决出胜负,我们可以先规定 如果是玩家赢 返回 * ,电脑赢 返回 # , 平局 返回 Q ,游戏继续 返回 A 。
判断思路:
先对行进行判断,判断是否有三个棋子连在一起的情况,然后再对列判断,最后对对角线判断。我先将判断的代码写死,之后有时间再来将他写活。

char Iswin(char board[ROW][COL] , int row,int col) {
	//判断数组
	//先判断行,再来列,再来对角线
	int i = 0;
	int j = 0;
	int indxtx = 0;
	int indxty = 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 (j = 0; j < COL; j++) {
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
			return board[0][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 'A';
}

当判断没有人赢的情况下,就来判断是否平局,我们来写个平局的代码 IsFull()。如果为平局返回 Q

如果不是平局的话返回 A

是否平局

判断平局要判断该数组是否满了,如果满了且元素不为 ‘空格’ ,则为平局,返回 1 。 反之 ,返回 0 。

//判断数组是否满了,满了返回 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;
}
game函数调用游戏函数

最后我们在 game 函数里,将上面写到的游戏函数给调用,将游戏函数串起来,并且在game 函数 末尾,对判断输赢的 Iswin 函数返回值进行判断,打印出结果。

void game() {

	char board[ROW][COL] = { 0 };
	//棋盘初始化
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
	char ret = ' ';
	while (1) {
		PlayMove(board,ROW,COL);
		DispalyBoard(board, ROW, COL);//下棋后打印
		printf("n");
		//判断输赢
		ret = Iswin(board , ROW,COL);
		if (ret != 'A') {//有结果了先跳出循环,再来判断结果什么
			break;
		}

		ComputerMove(board, ROW, COL);//电脑下棋
		DispalyBoard(board, ROW, COL);
		printf("n");
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'A') {
			break;
		}
	}
	if (ret == '*') {
		printf("玩家赢了...nn");
	}
	else if (ret == '#') {
		printf("电脑赢了...nn");
	}
	else if (ret == 'Q') {
		printf("平局...nn");
	}
}
函数的声明

在这个项目中会有不少函数的声明,所以我把所有函数声明写在一个 game.h 头文件里,直接调用该头文件即可。

#pragma once
#include
#include
#include

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//玩家下棋
void PlayMove( char board[ROW][COL],int row,int col);

//打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col);

//电脑下棋
//找空格随便下
void ComputerMove(char board[ROW][COL], int row, int col);

//判断输赢
char Iswin(char board[ROW][COL], int row, int col);

//判断数组是否满了
int IsFull(char board[ROW][COL], int row, int col);

因为本人技术

所有代码 game.h
#pragma once
#include
#include
#include

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//玩家下棋
void PlayMove( char board[ROW][COL],int row,int col);

//打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col);

//电脑下棋
//找空格随便下
void ComputerMove(char board[ROW][COL], int row, int col);

//判断输赢
char Iswin(char board[ROW][COL], int row, int col);

//判断数组是否满了
int IsFull(char board[ROW][COL], int row, int col);
game.c
#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");
															
		if (i < row - 1) {
			//printf("---|---|---n");
			int j = 0;
			for (j = 0; j < col; j++) {
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("n");
		}
		
	}
}


//玩家下棋
void PlayMove(char board[ROW][COL], int row, int col) {

	int i = 0;
	int j = 0;

	while (1) {

		printf("玩家请输入:>n");
		printf("请输入坐标:>");
		scanf("%d %d", &i, &j);

		if (i <= ROW && i > 0 && j <= COL && j > 0) {
			if (board[i - 1][j - 1] == ' ') {
				board[i - 1][j - 1] = '*';
				break;
			}
			else {
				printf("坐标被占用不能下该位置,请选择其他位置n");
				printf("n");
			}
		}
		else {
			printf("坐标非法请重新输入n");
		}
		printf("n");
	}
}


void ComputerMove(char board[ROW][COL], int row, int col) {

	printf("电脑下棋:>n");
	
	int i = 0;
	int j = 0;

	while (1) {

		i = rand() % row;//0 ~ 2
		j = rand() % col;//0 ~ 2

		if (board[i][j] == ' ') {
			board[i][j] = '#';
			break;
		}
	}

}


//玩家赢  - *
//电脑赢  - #
//平局    - Q
//游戏继续 - A

char Iswin(char board[ROW][COL] , int row,int col) {

	//判断数组
	//先判断行,再来列,再来对角线
	int i = 0;
	int j = 0;
	int indxtx = 0;
	int indxty = 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 (j = 0; j < COL; j++) {
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
			return board[0][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 'A';
}
//判断数组是否满了,满了返回 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;
}

test.c
#define  _CRT_SECURE_NO_WARNINGS
#include
#include "game.h"

//创建数组,数组初始化 : 空 格 ,打印表格
void menu() {

	printf("******************************n");
	printf("********** 1 . play **********n");
	printf("********** 0 . exit **********n");//选择 0 退出是为了后面只定义一个变量input ,可以作为循环判断与switch
	printf("******************************n");
}

void game() {

	char board[ROW][COL] = { 0 };
	//棋盘初始化
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
	char ret = ' ';
	while (1) {
		PlayMove(board,ROW,COL);
		DispalyBoard(board, ROW, COL);//下棋后打印
		printf("n");
		//判断输赢
		ret = Iswin(board , ROW,COL);
		if (ret != 'A') {//有结果了先跳出循环,再来判断结果什么
			break;
		}

		ComputerMove(board, ROW, COL);//电脑下棋
		DispalyBoard(board, ROW, COL);
		printf("n");
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'A') {
			break;
		}
	}
	if (ret == '*') {
		printf("玩家赢了...nn");
	}
	else if (ret == '#') {
		printf("电脑赢了...nn");
	}
	else if (ret == 'Q') {
		printf("平局...nn");
	}
}
int main() {

	srand((unsigned int)time(NULL));//设置生成随机数的起点
	int input = 0;
	do {
		menu();//菜单
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
			case 0:
				printf("退出游戏成功n");
				break;
			case 1:
				game();
				break;
			default:
				printf("输入错误n");
		}
	} while (input);
	return 0;
} 
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1037095.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号