基于EasyX用C语言写的进阶井字棋

                                                                             ——C语言期末大作业

游戏进阶玩法:当一方落下第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)
    }
    else
    {
        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

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值