相关文章推荐
寂寞的茄子  ·  Image edge mobile ...·  7 月前    · 
强悍的楼梯  ·  java post json数据-掘金·  1 年前    · 

游戏进阶玩法:当一方落下第4子仍未获胜时,则其落下的第1子会被拿掉,依次类推。

一、使用Visual Studio配置EasyX环境

EasyX是一个十分简单好用的 图形库 ,相比于其他制作图形界面的工具而言要容易上手的多,十分适初学者使用。使用EasyX写的GUI程序十分 简洁、明了。 因为DEV-C++不兼容EasyX,所以用 Visual Studio

下载EasyX:

官网: EasyX Graphics Library for C++

打开安装包,安装在Visual

二、代码编写游戏界面

1、画出棋盘

这只是画出游戏界面的一个函数而已

#include <graphics.h>//图形库头文件
#include<stdio.h>
#include<math.h>
void huamian()          //画出棋盘
	initgraph(800, 800);//创建图形窗口大小
	IMAGE img;	//准备图片
	loadimage(NULL,"背景.jpg",800,800); //打开图片
	setcolor(BLACK);设置线条黑色
	for (int i = 150;i <= 450;i += 100) { //划线
		line(i, 150, i, 450);
	for (int i = 150;i <= 450;i += 100) {
		line(150, i, 450, i);

其中loadimage函数是打开图片,需要把已经下载好的图片放在项目的文件中才能引用

 2、获取鼠标的信息

 鼠标点哪里,圈叉就在哪里

int i, j;
		m = GetMouseMsg();//获取一个鼠标信息
		int x, y,x1,y1,x2,y2;
		for (int i = 2;i < 5;i++) {
			for (int j = 2;j < 5;j++) {
				if (abs(m.x - i * 100) < 50 && abs(m.y - j * 100) < 50) {
					x = i * 100;
					y = j * 100;

其中  if (abs(m.x - i * 100) < 50 && abs(m.y - j * 100) < 50) 的判断非常重要

如果没有鼠标点哪里,哪里就会出现O/X。

我们不可能每次都点中鼠标的正中间,所以就用abs取绝对值来确定鼠标的误差在什么范围内。

这样就可以允许鼠标点击出现偏差也能在格子正中间显示出O/X。
3、画圈叉

void isCircle(int x,int y) //画圆
	setfillcolor(BLUE);//设置实心圆的颜色蓝色
	solidcircle(x, y, 30); //画圆的坐标,半径
void isCha(int i, int j)//画叉
	int x1, y1, x2, y2;
	int x = (i + 2) * 100;
	int y = (j + 2) * 100;
	setcolor(RED);
	x1 = x - 30;
	y1 = y - 30;
	x2 = x + 30;
	y2 = y + 30;
	line(x1, y1, x2, y2);
	line(x2, y1, x1, y2);

 由于是后期的函数,所以其中出现了很多其他数据

但不影响,其中最主要的是 solidcircle()和line()函数,

line(),画直线的函数,输入起点和终点的坐标即可

游戏界面的布局到这里就极其简陋的完成了。

三、核心进阶玩法设计

1、思路:

定义三维数组,chessBoard[a][x][y],其中x、y代表棋盘的横纵坐标都在(0、1、2)之间

而a代表在x、y这个位置上的属性,设计了有三种属性.

第0层代表该位置是否有棋子,0=没有,1=有。

第1层代表该位置是什么棋子,0=圆,1=叉

第2层代表该位置的深度(棋子存在的回合数),可取[0,7]

由于一方的棋子最多可以存在3个,下第四个时就要把第一个拿走,所以一颗棋子最多可以存在7个回合(呃~~~我定义了下一颗棋子就算一回合)

 三维数组创立完毕

衔接问题:

将处理过后的鼠标横纵坐标(在[0,2]间的整数)传递给一个函数,该函数返回一个三维数组

然后遍历这个三维数组信息,画出相对应的棋子。鼠标再点下一个位置,函数就再返回一个新的数组给我,最后清空画面,重新遍历,画出棋子以达到消除棋子的目的。

2、上代码

设计三维数组的函数

int chessBoard[3][3][3] ; //属性(0:是否有棋子,1:(O)或(X)子,2;第几次下的),y,x
static int count = 0;           //用于计数,static表示count变量作用域为当前目录,
void task1(int x, int y)
    chessBoard[0][y][x] = 1;
    if (count % 2 == 0)
        chessBoard[1][y][x] = 0; // 0代表黑子 (O)
        chessBoard[1][y][x] = 1; // 1代表白子(X)
    count++;
    addDepth();//增加深度  ,深度代表棋子存在的回合数
    clearChess(); //清理深度
    //output();
    // printf("%d\n", count);
    // printf("%d",chessBoard[0][y][x]);
void addDepth()
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            if (chessBoard[0][i][j] == 1) //如果有子
                chessBoard[2][i][j] ++;//深度增加1
void clearChess() {
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            if (chessBoard[2][i][j] == 7)//如果一颗棋子存在7个回合则清零
                chessBoard[2][i][j] = 0;//深度清零
                chessBoard[0][i][j] = 0;//该位置没有棋子

头文件:封装成库函数

#pragma once
#ifndef task1_h
#define task1_h
void task1(int x, int y);
void addDepth();
void output();
void clearChess();
extern int chessBoard[3][3][3];
#endif

衔接过程:

if (m.uMsg == WM_LBUTTONDOWN) {//如果鼠标左键单击,处理鼠标的坐标成棋盘坐标
			x = 0.01 * x - 2;
			y = 0.01 * y - 2;
			if (chessBoard[0][y][x] == 1) {//先判断这个地方是否有子,已经有子了就不能下了
				continue;//以防重复点击相同位置
			else {
				task1(x, y);//把坐标给task函数处理
				clearrectangle(0, 0, 800, 800);//清除画面
				huamian1();//重新画棋盘
				for (int i = 0;i < 3;i++) {//遍历棋盘的每一个位置
					for (int j = 0;j < 3;j++) {
						if (chessBoard[0][i][j] == 1) {//task返回给我三维数组,第0层代表是否有子
							if (chessBoard[1][i][j] == 0) {//第一层代表是圆还是叉
								isCircle(j, i);
							else if (chessBoard[1][i][j] == 1) {
								isCha(j, i);

其中huamian1()函数与huamian()函数相比,少了一句initgraph(800, 800); 若直接使用huamian()函数重新画一个棋盘则会一直创建新的窗口。(非常好玩

int main()
	huamian();
	playChess();
	while (1);//防止闪退
	return 0;

四、完整的全家桶

链接:GitHub - Nebula-Yong/Tic-Tac-Toe: 高阶井字棋,一方下第四个子时,其第一个子会被收回,纯C打造,基于easyX制作GUI。vs的项目文件https://github.com/Nebula-Yong/Tic-Tac-Toe

井字棋游戏的C语言实现,两方玩家可以玩井字棋printf("请输入操作前的数字代号:\n1:新游戏\n2:退出\n"); scanf_s("%d", &op); if (op == 2) break; else if (op == 1) new_game(); else { printf("请重新输入正确的数字:\n"); scanf_s("%d", &op); if (op == 2) break; else if (op == 1) new_game(); else { printf("未知错误,请重新加载游戏\n"); printf("已退出游戏\n"); 声明step变量为全局变量,这样函数内部就可以修改全局变量step的值x0和y0分别表示落子位置的左上角的x和y坐标。通过 index%3和 index // 3来计算出落子位置在棋盘上的行列坐标,并将其乘以117(每个格子的大小)来得到实际的像系坐标。x1和y1 则表示落子位置的右下角的x和y坐标,分别是 x0+117 和 y 0+ 117。说明在函数内部会对它进行修改或者读取。定义全局变量,设置一个列表出所有赢的可能方式。 这是在之前[【C++ 程序】 井字棋游戏(人 VS Lv3电脑)(战绩统计)的基础上运用 EasyX 图形库完成的可视化程序。 //This program is a simple tic-tac-toe game. 井字棋是一种在3 * 3格子上进行的连珠游戏,又称井字游戏。井字棋的游戏有两名玩家,其中一个玩家画圈,另一个玩家画叉,轮流在3 * 3格子上画上自己的符号,最先在横向、纵向、或斜线方向连成一条线的人为胜利方。如图1所示为画圈的一方为胜利者。