C语言小游戏1——三子棋

代码下载

Github源码下载地址:
https://github.com/Kyrie-leon/C_Project/tree/master/Three_Game

一、多文件思维

我们使用多文件实现三子棋游戏,培养多文件思维,分别为game.h、game.c和main.c

二、游戏总体思路与函数设计实现

三子棋游戏的主要思路为:
玩家通过菜单进入游戏->显示棋盘->玩家移动->判断输赢->电脑移动->判断输赢
上述函数封装在game.c文件中

2.1 游戏菜单Menu

void Menu()
{
    
    
	printf("################################\n");
	printf("####  1.Play        2.Exit  ####\n");
	printf("################################\n");
	printf("Please input your selection#: ");
}

2.2 显示棋盘ShowBoard

棋盘用一个二维数组来存储并显示,对于没有下过棋子的位置统一用’空格存储,由于电脑的分辨率不同,棋盘的形状需要不断调试。

void ShowBoard(char board[][COL],int row, int col)
{
    
    
	printf("   | 1 | 2 | 3 |\n");
	printf("----------------\n");
	//外层循环控制每一行,内层循环控制每一列
	for (int i = 0; i < ROW; i++)
	{
    
    
		printf(" %d | ",i+1);
		for (int j = 0; j < COL; j++) 
		{
    
    
			printf("%c | ", board[i][j]);
		}
		printf("\n----------------\n");
	}
}

2.3 玩家移动PlayerMove

玩家棋子用X表示,在输入位置后需要判断落子的地方是否合法,主要为如下情况
1.越界,即超出棋盘范围,
2. 落子位置被占用,即该位置已经存在玩家棋子或者电脑棋子

void PlayerMove(char board[][COL], int row, int col)
{
    
    
	//定义输入坐标x,y
	int x = 0;
	int y = 0;
	while (1) 
	{
    
    
		printf("请输入你的位置:");
		scanf("%d %d", &x, &y);
		if (x < 1 || x>3 || y < 1 || y>3)
		{
    
    
			printf("你输入的坐标有误!\n");
			continue;
		}
		//需要注意用户输入的坐标从1开始,而程序定义的棋盘坐标从0开始
		else if (board[x - 1][y - 1] != ' ')
		{
    
    
			printf("你输入的位置已经被占用!\n");
			continue;
		}
		else
		{
    
    
			board[x - 1][y - 1] = P_COLOR;
			break;
		}
	}
}

2.4 判断输赢Judge

判断输赢的几种情况已经在代码中给出注释,不懂的话可以评论问我

char Judge(char board[][COL], int row, int col)
{
    
    
	//1.遍历每一行是否三子成珠
	for (int 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];
		}
	}

	//2.遍历每一列是否三子成珠
	for (int j = 0; j < col; j++)
	{
    
    
		if (board[0][j] == board[1][j] && \
			board[1][j] == board[2][j] && \
			board[0][j] != ' ')
		{
    
    
			return board[0][j];
		}
	}

	//3.遍历九宫格对角线是否三子成珠
	if (board[0][0] == board[1][1] && \
		board[1][1] == board[2][2] && \
		board[0][0] != ' ')
	{
    
    
		return board[0][0];
	}

	if (board[0][2] == board[1][1] && \
		board[1][1] == board[2][0] && \
		board[0][2] != ' ')
	{
    
    
		return board[0][2];
	}
	//4.没有出现三子成珠,且棋盘还有空位,继续下棋
	for (int i = 0; i < row; i++)
	{
    
    
		for (int j = 0; j < col; j++)
		{
    
    
			if (board[i][j] == ' ')
			{
    
    
				return NEXT;
			}
		}
	}
	//5.上述条件都不满足,和棋
	return DRAW;
}

2.5 电脑移动ComputerMove

电脑落子我们使用随机落子,如果想要更加智能可以采取一些策略

void ComputerMove(char board[][COL], int row, int col)
{
    
    
	while (1)
	{
    
    
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = C_COLOR;
			break;
		}
	}
}

2.5 游戏主控制函数Game

void Game()
{
    
    
	//定义一个随机种子用于电脑落子
	srand((unsigned long)time(NULL));
	//定义棋盘
	char board[ROW][COL];
	//棋盘初始化为空
	memset(board, ' ', sizeof(board));
	//定义变量result用于判断输赢情况
	char result='x';
	do
	{
    
    
		ShowBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		//出现三子成珠,跳出循环,给出输赢结果
		if (result != NEXT)
		{
    
    
			break;
		}
		ComputerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		//出现三子成珠情况,跳出循环,给出输赢结果
		if (result != NEXT)
		{
    
    
			break;
		}
	} while (1);

	//打印输赢结果
	if (P_COLOR == result)
	{
    
    
		printf("你赢了!\n");
	}
	else if (C_COLOR == result)
	{
    
    
		printf("你输了!\n");
	}
	else
	{
    
    
		printf("和棋!\n");
	}
	//此处再次调用显示棋盘函数,用于显示最终的落子情况,如果不调用该函数,会出现看不到最后一次落子的棋盘
	ShowBoard(board, ROW, COL);
}

三、多文件代码清单

3.1 game.h

用于存放实现游戏的所有库函数和函数声明,以及一些宏定义方便后续更改
使用ifndef/define/endif防止头文件的重复包含和编译。

#ifndef _GAME_H
#define _GAME_H

#include <stdio.h>
#include <Windows.h>
#include <time.h>
#pragma warning(disable:4996)

//定义棋盘大小
#define ROW 3
#define COL 3
//定义玩家与电脑棋子颜色
#define P_COLOR 'X'
#define C_COLOR 'O'
#define NEXT 'N'
#define DRAW 'D'


void Menu();
void Game();

#endif


3.2 game.c

用于存放实现游戏的所有函数定义

#include "game.h"

void Menu()
{
    
    
	printf("################################\n");
	printf("####  1.Play        2.Exit  ####\n");
	printf("################################\n");
	printf("Please input your selection#: ");
}

void ShowBoard(char board[][COL],int row, int col)
{
    
    
	printf("   | 1 | 2 | 3 |\n");
	printf("----------------\n");
	//外层循环控制每一行,内层循环控制每一列
	for (int i = 0; i < ROW; i++)
	{
    
    
		printf(" %d | ",i+1);
		for (int j = 0; j < COL; j++) 
		{
    
    
			printf("%c | ", board[i][j]);
		}
		printf("\n----------------\n");
	}
}

void PlayerMove(char board[][COL], int row, int col)
{
    
    
	//定义输入坐标x,y
	int x = 0;
	int y = 0;
	while (1) 
	{
    
    
		printf("请输入你的位置:");
		scanf("%d %d", &x, &y);
		if (x < 1 || x>3 || y < 1 || y>3)
		{
    
    
			printf("你输入的坐标有误!\n");
			continue;
		}
		//需要注意用户输入的坐标从1开始,而程序定义的棋盘坐标从0开始
		else if (board[x - 1][y - 1] != ' ')
		{
    
    
			printf("你输入的位置已经被占用!\n");
			continue;
		}
		else
		{
    
    
			board[x - 1][y - 1] = P_COLOR;
			break;
		}
	}
}

char Judge(char board[][COL], int row, int col)
{
    
    
	//1.遍历每一行是否三子成珠
	for (int 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];
		}
	}

	//2.遍历每一列是否三子成珠
	for (int j = 0; j < col; j++)
	{
    
    
		if (board[0][j] == board[1][j] && \
			board[1][j] == board[2][j] && \
			board[0][j] != ' ')
		{
    
    
			return board[0][j];
		}
	}

	//3.遍历九宫格对角线是否三子成珠
	if (board[0][0] == board[1][1] && \
		board[1][1] == board[2][2] && \
		board[0][0] != ' ')
	{
    
    
		return board[0][0];
	}

	if (board[0][2] == board[1][1] && \
		board[1][1] == board[2][0] && \
		board[0][2] != ' ')
	{
    
    
		return board[0][2];
	}
	//4.没有出现三子成珠,且棋盘还有空位,继续下棋
	for (int i = 0; i < row; i++)
	{
    
    
		for (int j = 0; j < col; j++)
		{
    
    
			if (board[i][j] == ' ')
			{
    
    
				return NEXT;
			}
		}
	}
	//5.上述条件都不满足,和棋
	return DRAW;
}

void ComputerMove(char board[][COL], int row, int col)
{
    
    
	while (1)
	{
    
    
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = C_COLOR;
			break;
		}
	}
}

void Game()
{
    
    
	//定义一个随机种子用于电脑落子
	srand((unsigned long)time(NULL));
	//定义棋盘
	char board[ROW][COL];
	//棋盘初始化为空
	memset(board, ' ', sizeof(board));
	//定义变量result用于判断输赢情况
	char result='x';
	do
	{
    
    
		ShowBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		//出现三子成珠,跳出循环,给出输赢结果
		if (result != NEXT)
		{
    
    
			break;
		}
		ComputerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		//出现三子成珠情况,跳出循环,给出输赢结果
		if (result != NEXT)
		{
    
    
			break;
		}
	} while (1);

	//打印输赢结果
	if (P_COLOR == result)
	{
    
    
		printf("你赢了!\n");
	}
	else if (C_COLOR == result)
	{
    
    
		printf("你输了!\n");
	}
	else
	{
    
    
		printf("和棋!\n");
	}
	//此处再次调用显示棋盘函数,用于显示最终的落子情况,如果不调用该函数,会出现看不到最后一次落子的棋盘
	ShowBoard(board, ROW, COL);
}

3.3 main.c

实现三子棋游戏的主菜单和实现步骤

#include "game.h"

int main()
{
    
    
	int select=0;
	int quit = 0;
	while(!quit)
	{
    
    
		Menu();
		scanf("%d", &select);
		switch(select)
		{
    
    
			case 1:
				Game();
				break;
			case 2:
				quit = 1;
				break;
			default:
				printf("Please input again\n");
				break;
		}
	}

	printf("ByeBye!\n");

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40076022/article/details/109333325