Skip to content

Instantly share code, notes, and snippets.

@bcernesto
Last active August 10, 2018 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcernesto/94b19be8a124655d9b159f3507a6f8aa to your computer and use it in GitHub Desktop.
Save bcernesto/94b19be8a124655d9b159f3507a6f8aa to your computer and use it in GitHub Desktop.
Creación del juego Tres en Raya (gato, tic tac toe o similar) utilizando creación de vistas programáticas en Objective C.
/* Este archivo es solo una parte de la aplicación original, pero es el que incorpora toda la lógica.
Todo el código puede ser encontrado en GitHub en el siguiente repositorio:
https://github.com/bcernesto/Tres-En-Raya
Insisto: Este código no funcionará por sí solo! Es necesario clonar todo el repo */
// Importación de otros archivos
#import "ViewController.h"
#import "SoundManager.h"
#import "UIView+Toast.h"
@interface ViewController (){
// Creamos todas las variables que necesitaremos a nivel de Controller
NSMutableArray *arrayDeBotones;
UIButton *nuevoBoton;
UIView *menu;
float anchoVentana;
float altoVentana;
int jugador;
int jugada;
}@end
@implementation ViewController
// Método que se ejecutará cuando la app esté totalmente cargada, es decir, al inicio de la app.
- (void)viewDidLoad {
[super viewDidLoad];
// Establecemos valores iniciales para algunas variables
anchoVentana=self.view.bounds.size.width;
altoVentana=self.view.bounds.size.height;
jugador=1;
jugada=0;
[self agregarBotones];
// Los sonidos hacen uso de una librería externa, incluída en el repositorio
[[SoundManager sharedManager] setMusicVolume:0.2];
[[SoundManager sharedManager] playMusic:@"intro.mp3" looping:YES];
}
// Método que agrega todos los botones de la interfaz
- (void) agregarBotones{
// Establecemos algunas variables
float anchoBoton=anchoVentana/3;
float altoBoton=altoVentana/3;
arrayDeBotones = [[NSMutableArray alloc] init];
int x=0;
int y=0;
// Con un for, creamos los 9 botones que conformarán la interfaz
for (int i=0; i<9; i++) {
nuevoBoton = [[UIButton alloc] initWithFrame:CGRectMake(anchoBoton*x+1, altoBoton*y+1, anchoBoton, altoBoton)];
[nuevoBoton setBackgroundColor:[UIColor blueColor]];
[nuevoBoton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[nuevoBoton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
[nuevoBoton setAccessibilityLabel:@"Casilla vacía"];
[nuevoBoton addTarget:self action:@selector(botonPulsado:) forControlEvents:UIControlEventTouchUpInside];
nuevoBoton.tag = i;
nuevoBoton.titleLabel.font = [UIFont boldSystemFontOfSize:15];
nuevoBoton.layer.masksToBounds = YES;
nuevoBoton.layer.cornerRadius = 5;
nuevoBoton.layer.borderWidth = 1;
nuevoBoton.layer.borderColor = [[UIColor blackColor] CGColor];
[arrayDeBotones addObject:nuevoBoton];
if(x==2){
x=0;
y=y+1;
}else{
x=x+1;
}
}
// Agregamos todos los botones a la View principal
for(UIButton *boton in arrayDeBotones){
[self.view addSubview:boton];
}
}
// Método que se ejecutará cuando se pulse cualquiera de los botones
-(void) botonPulsado:(UIButton *) sender {
// Se comprueba que haya un turno, y que el botón no haya sido pulsado ya antes
if((jugador>0)&&([self tituloBoton:sender.tag]==nil)){
// Se realizan acciones dependiendo el turno del jugador que pulsó
switch(jugador){
case 1:
[sender setAccessibilityLabel:@"X"];
[sender setTitle:@"X" forState:UIControlStateNormal];
[[SoundManager sharedManager] playSound:@"gato.mp3" looping:NO];
break;
case 2:
[sender setAccessibilityLabel:@"O"];
[sender setTitle:@"O" forState:UIControlStateNormal];
[[SoundManager sharedManager] playSound:@"perro.mp3" looping:NO];
break;
}
// Se incrementa el contador de jugadas, y se hacen comprobaciones para saber si ha ganado alguno
jugada=jugada+1;
int resultado=[self ComprobarPartida];
if(resultado>0) {
[self finPartida:resultado];
}else{
[self turnoSiguiente];
}
}else{
[[SoundManager sharedManager] playSound:@"vaca.mp3" looping:NO];
}
}
// Método que cambia el turno al siguiente jugador, en caso de que no haya finalizado la partida con empate
-(void) turnoSiguiente{
switch(jugador){
case 1:
jugador=2;
break;
case 2:
jugador=1;
break;
}
// Se hace uso de una librería externa para crear avisos emergentes al estilo Android, también incluída en el repositorio
[self.view makeToast:[NSString stringWithFormat:@"Turno del jugador %i", jugador]
duration:3.0
position:CSToastPositionCenter];
}
// Método que comprueba si la partida ha finalizado con un empate (retorna 2), o si alguno ha ganado (retorna 1). De lo contrario retorna 0
- (int) ComprobarPartida{
if (([[self tituloBoton:0] isEqual:[self tituloBoton:1]])&&([[self tituloBoton:1] isEqual:[self tituloBoton:2]])) return 1;
if (([[self tituloBoton:3] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:5]])) return 1;
if (([[self tituloBoton:6] isEqual:[self tituloBoton:7]])&&([[self tituloBoton:7] isEqual:[self tituloBoton:8]])) return 1;
if (([[self tituloBoton:0] isEqual:[self tituloBoton:3]])&&([[self tituloBoton:3] isEqual:[self tituloBoton:6]])) return 1;
if (([[self tituloBoton:1] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:7]])) return 1;
if (([[self tituloBoton:2] isEqual:[self tituloBoton:5]])&&([[self tituloBoton:5] isEqual:[self tituloBoton:8]])) return 1;
if (([[self tituloBoton:0] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:8]])) return 1;
if (([[self tituloBoton:2] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:6]])) return 1;
if(jugada==9) return 2;
return 0;
}
// Método que obtiene el título de un botón, a partir de su tag
-(NSString*) tituloBoton:(int) tagBoton{
for(UIButton *boton in arrayDeBotones){
if(boton.tag==tagBoton) return boton.currentTitle;
}
return NULL;
}
// Método que notifica si la partida a finalizado y su resultado
-(void) finPartida:(int) resultado{
NSString *mensajeAlerta;
switch(resultado){
case 1:
mensajeAlerta=[NSString stringWithFormat:@"Ha ganado el jugador %i",jugador];
[[SoundManager sharedManager] playSound:@"aplausos.mp3" looping:NO];
break;
case 2:
mensajeAlerta=@"La partida ha finalizado con un empate";
[[SoundManager sharedManager] playSound:@"abucheo.mp3" looping:NO];
break;
}
UIAlertController *alerta = [UIAlertController
alertControllerWithTitle:@"¡Partida terminada!"
message:mensajeAlerta
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok=[UIAlertAction
actionWithTitle:@"Aceptar"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
[alerta dismissViewControllerAnimated:YES completion:nil];
[self menuPartida:mensajeAlerta];
}];
[alerta addAction:ok];
[self presentViewController:alerta animated:YES completion:nil];
}
// Método que da la opción de volver a jugar
-(void) menuPartida:(NSString*) mensaje{
jugador=0;
jugada=0;
[[SoundManager sharedManager] stopMusic:NO];
[[SoundManager sharedManager] stopAllSounds:NO];
for(UIButton *boton in arrayDeBotones){
[boton removeFromSuperview];
}
[arrayDeBotones removeAllObjects];
menu = [[UIView alloc]
initWithFrame:CGRectMake(20,20,anchoVentana-40,altoVentana-40)];
float anchoVistaMenu=menu.bounds.size.width;
float altoVistaMenu=menu.bounds.size.height;
UILabel *MenuEtiqueta = [[UILabel alloc]
initWithFrame:CGRectMake(0,0,anchoVistaMenu,altoVistaMenu/4*3)];
MenuEtiqueta.text=[NSString stringWithFormat:@"Partida terminada. %@", mensaje];
[menu addSubview:MenuEtiqueta];
UIButton *menuBoton = [[UIButton alloc]
initWithFrame:CGRectMake(0,altoVistaMenu/4*3+1,anchoVistaMenu,altoVistaMenu/4)];
[menuBoton setBackgroundColor:[UIColor blueColor]];
[menuBoton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[menuBoton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
[menuBoton setTitle:@"Jugar de nuevo" forState:UIControlStateNormal];
[menuBoton addTarget:self action:@selector(jugarDeNuevo:) forControlEvents:UIControlEventTouchUpInside];
menuBoton.tag = 9;
menuBoton.titleLabel.font = [UIFont boldSystemFontOfSize:15];
menuBoton.layer.masksToBounds = YES;
menuBoton.layer.cornerRadius = 5;
menuBoton.layer.borderWidth = 1;
menuBoton.layer.borderColor = [[UIColor blackColor] CGColor];
[menu addSubview:menuBoton];
[self.view addSubview:menu];
}
// Método que limpia las variables y la interfaz, y las regresa a su estado original para jugar nuevamente
-(void) jugarDeNuevo:(UIButton *) sender {
[menu removeFromSuperview];
[self agregarBotones];
jugador=1;
[[SoundManager sharedManager] playMusic:@"intro.mp3" looping:YES];
}
// Método incluído en todos los Controllers
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
/* Este archivo es solo una parte de la aplicación original, pero es el que incorpora toda la lógica.
Todo el código puede ser encontrado en GitHub en el siguiente repositorio:
https://github.com/bcernesto/Tres-En-Raya
Insisto: Este código no funcionará por sí solo! Es necesario clonar todo el repo */
// Importación de otros archivos
#import "ViewController.h"
#import "SoundManager.h"
#import "UIView+Toast.h"
@interface ViewController (){
// Creamos todas las variables que necesitaremos a nivel de Controller
NSMutableArray *arrayDeBotones;
UIButton *nuevoBoton;
UIView *menu;
float anchoVentana;
float altoVentana;
int jugador;
int jugada;
}@end
@implementation ViewController
// Método que se ejecutará cuando la app esté totalmente cargada, es decir, al inicio de la app.
- (void)viewDidLoad {
[super viewDidLoad];
// Establecemos valores iniciales para algunas variables
anchoVentana=self.view.bounds.size.width;
altoVentana=self.view.bounds.size.height;
jugador=1;
jugada=0;
[self agregarBotones];
// Los sonidos hacen uso de una librería externa, incluída en el repositorio
[[SoundManager sharedManager] setMusicVolume:0.2];
[[SoundManager sharedManager] playMusic:@"intro.mp3" looping:YES];
}
// Método que agrega todos los botones de la interfaz
- (void) agregarBotones{
// Establecemos algunas variables
float anchoBoton=anchoVentana/3;
float altoBoton=altoVentana/3;
arrayDeBotones = [[NSMutableArray alloc] init];
int x=0;
int y=0;
// Con un for, creamos los 9 botones que conformarán la interfaz
for (int i=0; i<9; i++) {
nuevoBoton = [[UIButton alloc] initWithFrame:CGRectMake(anchoBoton*x+1, altoBoton*y+1, anchoBoton, altoBoton)];
[nuevoBoton setBackgroundColor:[UIColor blueColor]];
[nuevoBoton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[nuevoBoton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
[nuevoBoton setAccessibilityLabel:@"Casilla vacía"];
[nuevoBoton addTarget:self action:@selector(botonPulsado:) forControlEvents:UIControlEventTouchUpInside];
nuevoBoton.tag = i;
nuevoBoton.titleLabel.font = [UIFont boldSystemFontOfSize:15];
nuevoBoton.layer.masksToBounds = YES;
nuevoBoton.layer.cornerRadius = 5;
nuevoBoton.layer.borderWidth = 1;
nuevoBoton.layer.borderColor = [[UIColor blackColor] CGColor];
[arrayDeBotones addObject:nuevoBoton];
if(x==2){
x=0;
y=y+1;
}else{
x=x+1;
}
}
// Agregamos todos los botones a la View principal
for(UIButton *boton in arrayDeBotones){
[self.view addSubview:boton];
}
}
// Método que se ejecutará cuando se pulse cualquiera de los botones
-(void) botonPulsado:(UIButton *) sender {
// Se comprueba que haya un turno, y que el botón no haya sido pulsado ya antes
if((jugador>0)&&([self tituloBoton:sender.tag]==nil)){
// Se realizan acciones dependiendo el turno del jugador que pulsó
switch(jugador){
case 1:
[sender setAccessibilityLabel:@"X"];
[sender setTitle:@"X" forState:UIControlStateNormal];
[[SoundManager sharedManager] playSound:@"gato.mp3" looping:NO];
break;
case 2:
[sender setAccessibilityLabel:@"O"];
[sender setTitle:@"O" forState:UIControlStateNormal];
[[SoundManager sharedManager] playSound:@"perro.mp3" looping:NO];
break;
}
// Se incrementa el contador de jugadas, y se hacen comprobaciones para saber si ha ganado alguno
jugada=jugada+1;
int resultado=[self ComprobarPartida];
if(resultado>0) {
[self finPartida:resultado];
}else{
[self turnoSiguiente];
}
}else{
[[SoundManager sharedManager] playSound:@"vaca.mp3" looping:NO];
}
}
// Método que cambia el turno al siguiente jugador, en caso de que no haya finalizado la partida con empate
-(void) turnoSiguiente{
switch(jugador){
case 1:
jugador=2;
break;
case 2:
jugador=1;
break;
}
// Se hace uso de una librería externa para crear avisos emergentes al estilo Android, también incluída en el repositorio
[self.view makeToast:[NSString stringWithFormat:@"Turno del jugador %i", jugador]
duration:3.0
position:CSToastPositionCenter];
}
// Método que comprueba si la partida ha finalizado con un empate (retorna 2), o si alguno ha ganado (retorna 1). De lo contrario retorna 0
- (int) ComprobarPartida{
if (([[self tituloBoton:0] isEqual:[self tituloBoton:1]])&&([[self tituloBoton:1] isEqual:[self tituloBoton:2]])) return 1;
if (([[self tituloBoton:3] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:5]])) return 1;
if (([[self tituloBoton:6] isEqual:[self tituloBoton:7]])&&([[self tituloBoton:7] isEqual:[self tituloBoton:8]])) return 1;
if (([[self tituloBoton:0] isEqual:[self tituloBoton:3]])&&([[self tituloBoton:3] isEqual:[self tituloBoton:6]])) return 1;
if (([[self tituloBoton:1] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:7]])) return 1;
if (([[self tituloBoton:2] isEqual:[self tituloBoton:5]])&&([[self tituloBoton:5] isEqual:[self tituloBoton:8]])) return 1;
if (([[self tituloBoton:0] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:8]])) return 1;
if (([[self tituloBoton:2] isEqual:[self tituloBoton:4]])&&([[self tituloBoton:4] isEqual:[self tituloBoton:6]])) return 1;
if(jugada==9) return 2;
return 0;
}
// Método que obtiene el título de un botón, a partir de su tag
-(NSString*) tituloBoton:(int) tagBoton{
for(UIButton *boton in arrayDeBotones){
if(boton.tag==tagBoton) return boton.currentTitle;
}
return NULL;
}
// Método que notifica si la partida a finalizado y su resultado
-(void) finPartida:(int) resultado{
NSString *mensajeAlerta;
switch(resultado){
case 1:
mensajeAlerta=[NSString stringWithFormat:@"Ha ganado el jugador %i",jugador];
[[SoundManager sharedManager] playSound:@"aplausos.mp3" looping:NO];
break;
case 2:
mensajeAlerta=@"La partida ha finalizado con un empate";
[[SoundManager sharedManager] playSound:@"abucheo.mp3" looping:NO];
break;
}
UIAlertController *alerta = [UIAlertController
alertControllerWithTitle:@"¡Partida terminada!"
message:mensajeAlerta
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok=[UIAlertAction
actionWithTitle:@"Aceptar"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
[alerta dismissViewControllerAnimated:YES completion:nil];
[self menuPartida:mensajeAlerta];
}];
[alerta addAction:ok];
[self presentViewController:alerta animated:YES completion:nil];
}
// Método que da la opción de volver a jugar
-(void) menuPartida:(NSString*) mensaje{
jugador=0;
jugada=0;
[[SoundManager sharedManager] stopMusic:NO];
[[SoundManager sharedManager] stopAllSounds:NO];
for(UIButton *boton in arrayDeBotones){
[boton removeFromSuperview];
}
[arrayDeBotones removeAllObjects];
menu = [[UIView alloc]
initWithFrame:CGRectMake(20,20,anchoVentana-40,altoVentana-40)];
float anchoVistaMenu=menu.bounds.size.width;
float altoVistaMenu=menu.bounds.size.height;
UILabel *MenuEtiqueta = [[UILabel alloc]
initWithFrame:CGRectMake(0,0,anchoVistaMenu,altoVistaMenu/4*3)];
MenuEtiqueta.text=[NSString stringWithFormat:@"Partida terminada. %@", mensaje];
[menu addSubview:MenuEtiqueta];
UIButton *menuBoton = [[UIButton alloc]
initWithFrame:CGRectMake(0,altoVistaMenu/4*3+1,anchoVistaMenu,altoVistaMenu/4)];
[menuBoton setBackgroundColor:[UIColor blueColor]];
[menuBoton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[menuBoton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
[menuBoton setTitle:@"Jugar de nuevo" forState:UIControlStateNormal];
[menuBoton addTarget:self action:@selector(jugarDeNuevo:) forControlEvents:UIControlEventTouchUpInside];
menuBoton.tag = 9;
menuBoton.titleLabel.font = [UIFont boldSystemFontOfSize:15];
menuBoton.layer.masksToBounds = YES;
menuBoton.layer.cornerRadius = 5;
menuBoton.layer.borderWidth = 1;
menuBoton.layer.borderColor = [[UIColor blackColor] CGColor];
[menu addSubview:menuBoton];
[self.view addSubview:menu];
}
// Método que limpia las variables y la interfaz, y las regresa a su estado original para jugar nuevamente
-(void) jugarDeNuevo:(UIButton *) sender {
[menu removeFromSuperview];
[self agregarBotones];
jugador=1;
[[SoundManager sharedManager] playMusic:@"intro.mp3" looping:YES];
}
// Método incluído en todos los Controllers
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment