《二吃一》游戏加蓝牙代码

article/2025/5/15 4:53:44

转载自:http://www.aisidachina.com/forum/thread-105-1-2.html

界面二吃一又名四步顶或是四棋,起源于中国民间。规则是两块吃一块,就是在一条直线上的自己的两个棋子可以吃掉对方的一个棋子。

在这说一下这个游戏的主要思想和大家分享一下,这个游戏分为双人模式和单人模式,双人模式主要是规则下边会简单介绍一下,人机对战涉及到比较复杂的算法想和大家一块探讨一下。
1.规则方法:
我用数组qizi存8个棋子,用数组position存17个位置,其实棋谱上有16个第17个是用来设置被吃的那个棋子的位置的。每个棋子都是一个Button,刚开始时想用UIImageView但是UIImageView不支持相应事件所以改为使用Button,每一个棋子都有不同的tag属性(从0到7)用来从数组中取对象,然后是用两个数组分别存双方棋子的位置从0到3和从12到15,每个数组4个对象,通过这两个数组把棋子和位置对应起来。每个棋子可以向4个方向走(用1、-1、4、-4表示),所以首先要判断是否越界了然后判断是否可以向这个方向移动,因为有可能那里已经有棋子了。然后要做的就是改变数组的值设置位置在界面上体现出来。
2.人机对战算法实现:
在以上规则的基础上添加玩家走棋后机器要执行的代码。主要是一个判断的过程,我分了三种情况(要建立三对数组分别存这三种情况所对应的棋子tag和方向),
首先模拟走一步棋,然后循环模拟对方(玩家)走每一步可以走的操作,
之后如果判断出可以吃掉对方(玩家)但不被玩家吃掉就把这个棋子的tag和走的方向放入第一对数组中,如果没吃掉对方也没被对方吃掉就放到第二对数组中,如果没吃掉对方的反而能被对方的吃掉就把它放到第三对数组中,其实这是一个循环的过程,
放完后随即取一个小于第一个数组个数的数从第一对数组中取出相应的值进行操作,如果第一对数组个数为零就从第二对数组中取值,之后是第是三个。这样我就取到了最理想的那个旗子和要做的操作,之后就按规则进行。

 

介绍一下这个实例实现的是两个带有蓝牙设备的touch之间的一个小游戏,在界面上有个可以响应事件的UIView(之前说过)可以点击,然后看谁新达到WINNING_TAP_COUNT (游戏中一常量可以自己设置)谁先达到谁就赢了,然后通知对方。还要引入GameKit.framework框架
头文件BlueToothViewController.h:

//
//
//  BlueToothViewController.h
//  BlueTooth
//
//  Created by mingchun liu on 09-11-24.
//  Copyright sdie 2009. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>

#define START_GAME_KEY @"startgame"
#define END_GAME_KEY @"endgame"
#define TAP_COUNT_KEY @"taps"
#define WINNING_TAP_COUNT 50

#define AMIPHD_P2P_SESSION_ID @"amiphdp2p2"//这个是蓝牙协议

@interface BlueToothViewController : UIViewController<GKPeerPickerControllerDelegate,GKSessionDelegate>{
        BOOL actingAsHost;//是否提供服务,客户端还是服务器端
        int playerTapCount;//记录玩家点击次数
        int opponentTapCount;//对方点击次数
        IBOutlet UILabel *playerTapCountLabel;//显示玩家点击次数
        IBOutlet UILabel *opponentTapCountLabel;//显示对手点击次数
        NSString *opponentID;//对方标识符
        GKSession *gkSession;
       
        IBOutlet UILabel *startQuitButton;//开始退出按钮
}

@property BOOL actingAsHost;
@property int playerTapCount;
@property int opponentTapCount;
@property (nonatomic,retain) GKSession *gkSession;

@property (nonatomic,retain) NSString *opponentID;

@property (nonatomic,retain)UILabel *playerTapCountLabel;
@property (nonatomic,retain)UILabel *opponentTapCountLabel;

@property (nonatomic,retain)UILabel *startQuitButton;


-(IBAction) handleStartQuitTapped;//处理开始退出操作
-(IBAction) handleTapViewTapped;//处理点击UIView的操作
-(void) updateTapCountLabels;//更新显示
-(void) initGame;//初始化游戏
-(void) hostGame;
-(void) joinGame;//加入游戏
-(void) endGame;//结束游戏
-(void) showEndGameAlert;//弹出结束游戏对话框
@end

 

 

下面是BlueToothViewController.m:

 

 

 

//
//  BlueToothViewController.m
//  BlueTooth
//
//  Created by mingchun liu on 09-11-24.
//  Copyright sdie 2009. All rights reserved.
//

#import "BlueToothViewController.h"

@implementation BlueToothViewController

@synthesize actingAsHost;
@synthesize playerTapCount;
@synthesize opponentID;
@synthesize playerTapCountLabel;
@synthesize opponentTapCountLabel;


@synthesize startQuitButton;
@synthesize gkSession;
@synthesize opponentTapCount;

-(IBAction) handleStartQuitTapped {//建立链接操作,弹出链接窗口显示在线
        if (! opponentID) {//如果对手ID为空就建立服务端提供服务
                actingAsHost = YES;
                GKPeerPickerController *peerPickerController =[[GKPeerPickerController alloc] init];
                peerPickerController.delegate = self;
                peerPickerController.connectionTypesMask =
                GKPeerPickerConnectionTypeNearby;
                [peerPickerController show];
        }
}
-(IBAction) handleTapViewTapped {//点击操作
        playerTapCount++;
        [self updateTapCountLabels];
        // did we just win?
        BOOL playerWins = playerTapCount >= WINNING_TAP_COUNT;//当点击达到一定次数时
        // send tap count to peer
        NSMutableData *message = [[NSMutableData alloc] init];//传的数据类型为nsdata类型的
        NSKeyedArchiver *archiver =
        [[NSKeyedArchiver alloc] initForWritingWithMutableData:message];
        [archiver encodeInt:playerTapCount forKey: TAP_COUNT_KEY];
        if (playerWins)
                [archiver encodeBool:YES forKey:END_GAME_KEY];
        [archiver finishEncoding];//打包传数据
        GKSendDataMode sendMode =
        playerWins ? GKSendDataReliable : GKSendDataUnreliable;//判断用可靠的链接还是不可靠的链接
        [gkSession sendDataToAllPeers: message withDataMode:sendMode error:NULL];//发送数据
        [archiver release];
        [message release];
        // also end game locally
        if (playerWins)
                [self endGame];
}

-(void) updateTapCountLabels {
        playerTapCountLabel.text =
        [NSString stringWithFormat:@"%d", playerTapCount];
        opponentTapCountLabel.text =
        [NSString stringWithFormat:@"%d", opponentTapCount];
}
-(void) initGame {
        playerTapCount = 0;
        opponentTapCount = 0;
}
-(void) hostGame {
        [self initGame];
        NSMutableData *message = [[NSMutableData alloc] init];
        NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]
                                                                 initForWritingWithMutableData:message];
        [archiver encodeBool:YES forKey:START_GAME_KEY];
        [archiver finishEncoding];
        NSError *sendErr = nil;
        [gkSession sendDataToAllPeers: message
                                         withDataMode:GKSendDataReliable error:&sendErr];
        if (sendErr)
                NSLog (@"send greeting failed: %@", sendErr);
        // change state of startQuitButton
        startQuitButton.text = @"Quit";
        [message release];
        [archiver release];
        [self updateTapCountLabels];
}
-(void) joinGame {
        [self initGame];
        startQuitButton.text = @"Quit";
        [self updateTapCountLabels];
}

 

//一下是代理方法

-(GKSession *) peerPickerController: (GKPeerPickerController*) controller
                  sessionForConnectionType: (GKPeerPickerConnectionType) type {
        if (!gkSession) {//如果没有链接时建立连接
                gkSession = [[GKSession alloc]
                                         initWithSessionID:AMIPHD_P2P_SESSION_ID//根据此值判断用的是什么链接
                                         displayName:nil//在线用户名
                                         sessionMode:GKSessionModePeer];
                gkSession.delegate = self;
        }
        return gkSession;
}

- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{//当picker接收到数据后将其释放掉,否则进入不了界面
        [picker dismiss];
        picker.delegate = nil;
        [picker autorelease];
}
- (void)session:(GKSession *)session
didReceiveConnectionRequestFromPeer:(NSString *)peerID {//已接受连接请求的代理方法
        actingAsHost = NO;//设为客户端
}

- (void)session:(GKSession *)session peer:(NSString *)peerID
didChangeState:(GKPeerConnectionState)state {//状态改变时触发的代理方法
        switch (state)
        {
                case GKPeerStateConnected:
                        [session setDataReceiveHandler: self withContext: nil];
                        opponentID = peerID;//改变opponentID的值
                        actingAsHost ? [self hostGame] : [self joinGame];//
                        break;
        }
}

- (void) receiveData: (NSData*) data fromPeer: (NSString*) peerID
                   inSession: (GKSession*) session context: (void*) context {//接受数据时的代理操作
        NSKeyedUnarchiver *unarchiver =
        [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        if ([unarchiver containsValueForKey:TAP_COUNT_KEY]) {
                opponentTapCount = [unarchiver decodeIntForKey:TAP_COUNT_KEY];
                [self updateTapCountLabels];
        }
        if ([unarchiver containsValueForKey:END_GAME_KEY]) {
                [self endGame];
        }
        if ([unarchiver containsValueForKey:START_GAME_KEY]) {
                [self joinGame];
        }
        [unarchiver release];
}
//以上是代理方法

 

-(void) showEndGameAlert {
        BOOL playerWins = playerTapCount > opponentTapCount;
        UIAlertView *endGameAlert = [[UIAlertView alloc]
                                                                 initWithTitle: playerWins ? @"Victory!" : @"Defeat!"
                                                                 message: playerWins ? @"Your thumbs have emerged supreme!":
                                                                 @"Your thumbs have been laid low"
                                                                 delegate:nil
                                                                 cancelButtonTitle:@"OK"
                                                                 otherButtonTitles:nil];
        [endGameAlert show];
        [endGameAlert release];
}
-(void) endGame {
        opponentID = nil;
        startQuitButton.text = @"Find";
        [gkSession disconnectFromAllPeers];
        [self showEndGameAlert];
}


/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
*/


/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
        // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
       
        // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
}


- (void)dealloc {
        [opponentID release];
        [playerTapCountLabel release];
        [opponentTapCountLabel release];

        [startQuitButton release];
        [gkSession release];
    [super dealloc];
}

@end


http://chatgpt.dhexx.cn/article/PYXDSo8N.shtml

相关文章

今天出去吃了一下午小吃~

转载于:https://www.cnblogs.com/keaideweiwei/archive/2012/12/07/2807834.html

吃一吃

1.给/dev/sdb2分区创建文件系统&#xff0c;类型为ext3mkfs -t ext3 /dev/sdb22.列出磁盘分区信息fdisk -l3.找到根目录下用户为root&#xff0c;权限为644的文件&#xff0c;修改权限为其他用户没有权限find / -user root -a -prem 644 -exec chomd 640 {} \;4./etc/passwd文件…

CSS行高的测量

一般默认的字体大小为16px行高是相邻行“基线”之间的距离&#xff0c;是包含行间距的 使用line-height设置行高时&#xff0c;除去字体大小剩下的距离会在行的上边和下边平分&#xff0c;即&#xff1a;行高字体大小上边距下边距&#xff08;同时上边距等于下边距&#xff09;…

css 行高解析

line-height:1.5; //行高不设置单位时&#xff0c;为当前元素字体大小*1.5不是文字撑开了div的高度&#xff0c;而是line-height .test1{font-size:20px; line-height:0; border:1px solid #cccccc; background:#eeeeee;} .test2{font-size:0; line-height:20px; border:1px s…

css设置1.5倍行高,css设定行高、绝对定位

设定行高2种方式 使用width、height(假定现宽38,高22 &#xff1b;目标宽70&#xff0c;高30) .welcome{ width: 70px; height: 30px; line-height: 30px; text-align: center; } 使用padding .welcome{ padding: 4px 16px; line-height: 22px; } 补充&#xff1a; 使用width、…

CSS 行高 line-height属性

在CSS中&#xff0c;通过 line-height属性来定义行高&#xff0c;行高是指相邻两行文本基线之间的垂直距离。 那什么是基线呢&#xff1f;对任何一个行内非替换元素&#xff0c;其内容区都会存在四条假想的线&#xff0c;分别是底线&#xff08;bottom&#xff09;、基线&…

P53-前端基础CSS-行高设置

P53-前端基础CSS-行高设置 1.概述 行高&#xff08;line height&#xff09; 行高指的是文字占有的实际高度可以通过line-height来设置行高 行高可以直接指定一个大小&#xff08;px em&#xff09;也可以直接为行高设置一个整数如果是一个整数的话&#xff0c;行高将会是字体…

CSS行高背景

一.行高 1.定义&#xff1a; 行高上距离内容高度下距离 其中 上距离下距离 2.应用场景 让单行文本在盒子中垂直居中对齐。在浏览器中行高是跟随字体大小变化的。 所以我们让文字的行高等于盒子的高度。 div{ height:50px; line-height:50px; } 3.行高与盒子高度的三种关系 如…

css控制文本的行高

line-height可以控制文本的行高 示例 <p> 这是一个标准行高的段落。 在大多数浏览器默认行高约20 px。 这是一个标准行高的段落。 这是一个标准行高的段落。 </p> <p class"p1"> 这是一个更小行高的段落。 这是一个更小行高的段落。 这是一个更小…

CSS行高line-height属性理解及应用

行高的概念看上去很简单——文字行的高度&#xff0c;其实&#xff0c;行高所涉及到的基础知识&#xff0c;对于今后理解其它属性也很重要。 大片密密麻麻的文字往往会让人觉得乏味&#xff0c;因此适当地调整行高&#xff08;line-height&#xff09;可以减低阅读的困难与枯…

css行高和盒子高区别

行高 什么是行高 在css中所有的行都有自己的行高。 .box1 {border: 1px solid black;width: 200px; }<div class"box1">我是文字</div>被撑起来的高度就是行高 line-height属性 line-height: 60px;80px就是行高 注意点&#xff1a; 1.行高和盒子的…

css 行高

1. 什么是行高&#xff0c;以及行高的概念 我们可以试想一下&#xff0c;为什么会要有行高。我现在不需要行高不是完全可以的嘛。 我们可以仔细看看这个&#xff0c;这不是很正常的嘛。 那我们来看看这个&#xff0c;那当我们第一次看到这个的时候你觉得是横着度&#xff0c;…

css行高(line-height)及文本垂直居中原理

css行高&#xff08;line-height&#xff09;及文本垂直居中原理 一、行高的定义 标准定义&#xff1a;两行文字基线之间的距离。 那么什么是基线&#xff1f; 基线是在英文字母中用到的一个概念&#xff0c;我们刚学英语的时使用的那个英语本子每行有四条线。在 CSS 中&am…

css设置1.5倍行高,CSS怎么控制行高?

CSS怎么控制行高&#xff1f; css中&#xff0c;调整每行文字字体间距(行距)是使用line-height属性。 ● line-height 属性设置行间的距离(行高)。 注&#xff1a;不允许使用负值。 要实现上下换行文字行间距行高样式其实我们只用对文字所在对象设置line-height样式即可&#x…

css字行高怎么设,css文本行高怎么设置-电脑自学网

css文本行高的设置方法&#xff1a;首先新建文件&#xff0c;使用div标签创建一行文字&#xff1b;然后编写样式&#xff0c;设置div标签的class属性为mybkkd&#xff1b;最后通过div标签的class属性mybkkd设置文字上下的行高。 本教程操作环境&#xff1a;windows7系统、css3版…

CSS行高(line-height)使文本垂直居中详解

一.场景重现 在我们的静态页面设计中&#xff0c;在我们的块级元素中写入文字时&#xff1a; <div class"center">我想在中间</div> .center{height: 50px;background-color: #008c8c;} 会发现我们最后在网页显示的效果为&#xff1a; 这明显不太美观…

CSS行高

CSS行高 line-height 一.网页中的文本 文本中的每一个字符都有一个不可见的框&#xff0c;这些框又被放在两条不可见的横线中&#xff08;垂直居中&#xff09;&#xff0c;两条横线的距离就是行高&#xff0c;放个图片理解下 二.行高的设置方法 1.直接设置 p{ line-heigh…

css行高包含哪些,详解CSS行高

“行高”即CSS中line-height所描述的属性&#xff0c;它表示两行文字间基线之间的距离&#xff0c;不允许使用负值。在弄清行高之前&#xff0c;我们先来了解几个概念: 顶线、中线、基线、底线 上图所示线条从上到下为&#xff1a; 1 2 3 4 5 6 7 8 9 10 vertical-align:top; /…

CSS行高——line-height

初入前端的时候觉得CSS知道display、position、float就可以在布局上游刃有余了&#xff0c;随着以后工作问题层出不穷&#xff0c;才逐渐了解到CSS并不是几个style属性那么简单&#xff0c;最近看了一些关于行高的知识&#xff0c;就此总结一下。 所谓行高是指文本行基线间的垂…

深入理解css行高line-height

1.行高的定义 行高是相邻两行文本基线之间的垂直距离。看清楚是基线&#xff0c;估计有很多前端搞了几年的都说不出个所以然。小时候我们写英文26个英文字母的单词本&#xff08;随便找个图&#xff09; 一行里面有四条线&#xff0c;在css中一个行内非替换元素&#xff08;例…