Código Fonte da Interface:

#ifdef _WIN32

#include <windows>

#endif

#include <GL/glut.h>

#include <cmath>

#include "jogo.hpp"

#define FI_MIN .4

float teta(5.40732), fi(.937066), raio(12.);

int xant, yant;

bool rodando(false), arrastando(false);

Jogo jogo;

int H;

double X, Y, Z;

float const LARG = 10./7.;

int ii, ji;

GLuint peca, posicao;

GLint matrizViewport[4];

GLdouble matrizModelview[16], matrizProjecao[16];

bool luz(true), procurando(false), acabou(false);

// Mostra texto na tela

void mostrar(char * c) {

glRasterPos3f(-1, -1, .3);

while (*c)

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *c++);

}

// Checa intervalo de angulos

inline void checar_angulos() {

if (fi < FI_MIN) fi = FI_MIN;

else if (fi > M_PI/2.) fi = M_PI/2.;

if (teta < 0.) teta += M_PI * 2.;

else if (teta > M_PI * 2.) teta -= M_PI * 2.;

}

void linhas(float max, float x) {

glVertex3f(x, max*LARG, .01);

glVertex3f(x, -max*LARG, .01);

glVertex3f(max*LARG, x, .01);

glVertex3f(-max*LARG, x, .01);

}

void desenhar_posicao() {

GLfloat tabu[] = {1., 1., 1., 0.};

GLfloat posi[] = {.1, .1, .1, 0.};

glPushMatrix();

glPushMatrix();

glMaterialfv(GL_FRONT, GL_DIFFUSE, posi);

glColor3f(.0, .0, .0);

glTranslatef(0., 0., -.25);

glScalef(LARG*3., LARG*7., .5);

glutSolidCube(1.);

glScalef(7./3., 3./7., 1.);

glutSolidCube(1.);

glPopMatrix();

glMaterialfv(GL_FRONT, GL_DIFFUSE, tabu);

glTranslatef(0., 0., -.75);

glScalef(2.5, 2.5, .1);

glColor3f(.5, .5, .5);

glutSolidCube(5.);

glPopMatrix();

glColor3f(0, 0, 0);

glBegin(GL_LINES);

for (float x = -3.5*LARG; x <= 3.5 * LARG; x += LARG)

linhas(1.5, x);

for (float x = -1.5*LARG; x <= 1.5 * LARG; x += LARG)

linhas(3.5, x);

glEnd();

}

void desenhar_peca() {

GLfloat cor_peca[] = {.9, .8, .7, 0.};

GLUquadric * quad = gluNewQuadric();

glMaterialfv(GL_FRONT, GL_DIFFUSE, cor_peca);

glColor3f(1., 1., 1.);

gluCylinder(quad, .3, .3, .5, 10, 10);

glTranslatef(0., 0., .5);

gluSphere(quad, .3, 12, 12);

gluDeleteQuadric(quad);

}

void desenhar() {

GLfloat luz[] = { 1.0, 1.0, 1.0, 0.0};

GLfloat pos1[] = { 0., 0., 10., 0.};

glPushMatrix();

// Limpar tela

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Posicionamento

gluLookAt(raio*cos(teta)*cos(fi), -raio*sin(teta)*cos(fi), raio*sin(fi), 0., 0., 0., -sin(fi)*cos(teta), sin(fi)*sin(teta), cos(fi));

if (acabou)

mostrar("Jogo Encerrado");

glCallList(posicao);

// Pecas

for (int i = 0; i < 7; ++i)

for (int j = 0; j < 7; ++j)

if ((i != ii || j != ji) && jogo(i, j)) {

glPushMatrix();

glTranslatef((i-3)*LARG, (j-3)*LARG, 0.);

glCallList(peca);

glPopMatrix();

}

// Peca enquanto movendo

if (arrastando) {

glPushMatrix();

glTranslatef(X, Y, 0.);

glCallList(peca);

glPopMatrix();

}

glLightfv(GL_LIGHT1, GL_DIFFUSE, luz);

glLightfv(GL_LIGHT1, GL_POSITION, pos1);

glGetIntegerv(GL_VIEWPORT, matrizViewport);

glGetDoublev(GL_MODELVIEW_MATRIX, matrizModelview);

glGetDoublev(GL_PROJECTION_MATRIX, matrizProjecao);

glPopMatrix();

glutSwapBuffers();

}

void mapear(int x, int y, double & x1, double & y1, double & z1) {

GLfloat z;

glReadPixels(x, H-y-1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);

gluUnProject (x, H-y-1, z, matrizModelview, matrizProjecao, matrizViewport, &x1, &y1, &z1);

}

void movimento(int x, int y) {

if (rodando) {

fi += (y-yant)/500.;

teta += (x-xant)/500.;

xant = x;

yant = y;

checar_angulos();

desenhar();

}

if (arrastando) {

mapear(x, y, X, Y, Z);

desenhar();

}

}

void mouse(int button, int state, int x, int y) {

switch (button) {

case GLUT_RIGHT_BUTTON:

if (rodando = state == GLUT_DOWN) { // botao direito foi pressionado

xant = x;

yant = y;

}

break;

case GLUT_LEFT_BUTTON:

mapear(x, y, X, Y, Z);

int i = int(X/LARG + 3.5), j = int(Y/LARG + 3.5);

if (state == GLUT_DOWN) { // Botao esquerdo foi pressionado

if (jogo.pode_origem(i,j)) {

ii = i;

ji = j;

arrastando = true;

desenhar();

}

} else if (arrastando) { // Botao esquerdo foi solto

jogo.mover(ii, ji, i, j);

arrastando = false;

ii = ji = -1;

acabou = !jogo.pode_jogar();

desenhar();

}

}

}

void teclado(unsigned char tecla, int x, int y) {

bool redesenhar(true);

switch (tecla) {

case 'n': jogo.reiniciar(); acabou = false; break;

case 'l': ((luz = !luz) ? glEnable : glDisable)(GL_LIGHTING); break;

case '+': raio -= .5; break;

case '-': raio += .5; break;

case 'q': case 27: exit(0);

default: redesenhar = false;

}

if (raio < 2.) raio = 2.;

if (redesenhar) desenhar();

}

void especial(int key, int x, int y) {

bool redesenhar(true);

switch (key) {

case GLUT_KEY_LEFT: teta += .09; break;

case GLUT_KEY_RIGHT: teta -= .09; break;

case GLUT_KEY_UP: fi += .09; break;

case GLUT_KEY_DOWN: fi -= .09; break;

default: redesenhar = false;

}

if (redesenhar) {

checar_angulos();

desenhar();

}

}

GLuint criar_lista(void (*func)()) {

GLuint res = glGenLists(1);

glNewList(res, GL_COMPILE);

func();

glEndList();

return res;

}

void iniciar() {

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT1);

glClearColor(0., 0., 0., 0.);

glEnable(GL_DEPTH_TEST);

// Cria listas

peca = criar_lista(desenhar_peca);

posicao = criar_lista(desenhar_posicao);

}

void reshape(int w, int h) {

H = h;

glViewport (0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(65.0, GLfloat(w)/h, 1.0, 100.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main(int argc, char ** argv) {

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

glutCreateWindow("Jogo Resta 1");

iniciar();

glutKeyboardFunc(teclado);

glutReshapeFunc(reshape);

glutDisplayFunc(desenhar);

glutSpecialFunc(especial);

glutMouseFunc(mouse);

glutMotionFunc(movimento);

//glutFullScreen();

desenhar();

glutMainLoop();

return 0;

}

Código Fonte da Lógica do Jogo: (Jogo.cpp)

#include "jogo.hpp"

#include <cstdlib>

// Tabuleiro inicial, "#" indica posicao invalida, "P" indica Peca, "B" posicao em Branco (livre)

char inicial[7][8] = {

"##PPP##",

"##PPP##",

"PPPPPPP",

"PPPBPPP",

"PPPPPPP",

"##PPP##",

"##PPP##"

};

// Construtor da classe jogo, reinicia o mesmo

Jogo::Jogo() { reiniciar(); }

// Reinicio copia a configuracao inicial (acima) para o tabuleiro do jogo

void Jogo::reiniciar() { memcpy(tab, inicial, sizeof(tab)); }

// Verifica se a jogada de (dx,dy) para (px,py) eh valida. Eh assumido que a posicao (dx,dy) jah tenha sido verificada com "pode_origem".

bool Jogo::pode_mover(int dx, int dy, int px, int py) const {

return (valida(px, py) && tab[px][py] == 'B' &&

((px == dx && abs(dy-py) == 2) || (py == dy && abs(dx-px) == 2)) &&

tab[(px-dx)/2 + dx][(py-dy)/2 + dy] == 'P');

}

// Verifica o movimento de (dx,dy) para (px,py), e o executa caso seja possivel, atualizando o tabuleiro.

bool Jogo::mover(int dx, int dy, int px, int py) {

if (pode_mover(dx, dy, px, py)) {

tab[px][py] = 'P';

tab[dx][dy] = tab[(px-dx)/2 + dx][(py-dy)/2 + dy] = 'B';

return true;

}

return false;

}

// Verifica se o jogador ainda tem algum movimento possivel, no pior caso (quando o jogador nao tem mais movimentos) testa todas as possibilidades de jogada.

bool Jogo::pode_jogar() const {

static int const T[4][2] = {{-2,0},{2,0},{0,-2},{0,2}};

for (unsigned i(0); i < 7; ++i)

for (unsigned j(0); j < 7; ++j)

if (pode_origem(i, j))

for (unsigned t(0); t < sizeof(T)/sizeof(*T); ++t)

if (pode_mover(i, j, i+T[t][0], j+T[t][1]))

return true;

return false;

}

 

Código Fonte da Lógica do Jogo: (Jogo.hpp)

#ifndef _JOGO_H_

#define _JOGO_H_

#include <iostream>

using namespace std;

class Jogo {

public:

Jogo(); // construtor

void reiniciar(); // reiniciar o jogo

bool pode_jogar() const; // verifica se ainda ha jogadas possiveis

// verifica se pode mover de (dx, dy) para (px, py)

bool pode_mover(int dx, int dy, int px, int py) const;

// verifica se a posicao (i,j) eh uma origem de movimento valida

bool pode_origem(int i, int j) const { return valida(i,j) && tab[i][j]=='P'; }

// executa, se for possivel, o movimento de (dx,dy) para (px,py)

bool mover(int dx, int dy, int px, int py);

// verifica se a posicao (i,j) tem uma peca

bool operator()(int i, int j) const { return tab[i][j] == 'P'; }

// verifica se a posicao (i,j) eh uma posicao valida

bool valida(unsigned i, unsigned j) const { return i<7 && j<7 && tab[i][j]!='#'; }

private:

char tab[7][8]; // tabuleiro do objeto instanciado

};

#endif