Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

CSC112 Spring 2016 Examples

2370 views
head	1.1;
access;
symbols;
locks; strict;
comment	@// @;


1.1
date	2016.03.17.15.59.57;	author pngwen;	state Exp;
branches;
next	;


desc
@@


1.1
log
@Initial revision
@
text
@// Functions for the TrianglePuzzle Class
// Revision: $Revision$
// Change Log
//   $Log$

#include <iostream>
#include <unistd.h>
#include "tty_functions.h"
#include "trianglePuzzle.h"
#include "keystream.h"
#include "termmanip.h"

using namespace std;


TrianglePuzzle::TrianglePuzzle(int _x, int _y) : Widget(_x, _y, 27, 9), pegs(5)
{
  int coff = 12;
  int roff = 0;
  
  //build the puzzle
  for(int row=1; row<=5; row++) {
    for(int col=0; col < row; col++) {
      pegs[row-1].push_back(new Peg(_x + coff + (col * 6), _y+roff));
      if(row != 1) {
	pegs[row-1][col]->place();
      }
    }
    
    //update the offsets
    roff+=2;
    coff-=3;
  }

  //set up the cursor stuff
  this->cx = this->cy = 0;
  this->mx = this->my = -1;

  //select the default peg
  this->pegs[this->cy][this->cx]->select();
}


TrianglePuzzle::TrianglePuzzle() : TrianglePuzzle(1, 1)
{
  //put ourselves in the middle of the screen
  ttySize size = ttyGetSize(STDIN_FILENO);

  //compute the midpoint
  int mx = size.cols / 2 - 13;
  int my = size.rows / 2 - 4;

  //set ourselves to the midpoint and then adjust for the offset
  x(mx);
  y(my);
  for(auto ritr=pegs.begin(); ritr!=pegs.end(); ritr++) {
    for(auto citr=ritr->begin(); citr != ritr->end(); citr++) {
      (*citr)->x((*citr)->x() + mx);
      (*citr)->y((*citr)->y() + my);
    }
  }
}


TrianglePuzzle::~TrianglePuzzle()
{
  //delete all the pegs!
  for(auto ritr=pegs.begin(); ritr!=pegs.end(); ritr++) {
    for(auto citr=ritr->begin(); citr != ritr->end(); citr++) {
      delete *citr;
    }
  }
}

void
TrianglePuzzle::display()
{
  //display all the pegs
  for(auto ritr=pegs.begin(); ritr!=pegs.end(); ritr++) {
    for(auto citr=ritr->begin(); citr != ritr->end(); citr++) {
      (*citr)->display();
    }
  }
}

//select a given peg
void
TrianglePuzzle::selectPeg(int px, int py)
{
  //unselect the current one
  pegs[cy][cx]->deselect();

  //correct potential issues in y first
  if(py < 0) {
    //torus up!
    py = pegs.size() - 1;
  } else if (py >= pegs.size()) {
    //torus down!
    py = 0;
  }

  //correct x
  if(px < 0) {
    //torus left!
    px = pegs[py].size() -1;
  } else if(px >= pegs[py].size()) {
    //torus right!
    px = 0;
  }

  //select the chosen one and redisplay
  this->cx = px;
  this->cy = py;
  pegs[cy][cx]->select();
  display();
}


//move the selection up a row
void
TrianglePuzzle::up()
{
  //kick it up a notch
  selectPeg(cx, cy-1);
}


//move the selection down a row
void
TrianglePuzzle::down()
{
  //bring it on down
  selectPeg(cx, cy+1);
}


//move the selection right a column
void
TrianglePuzzle::right()
{
  //to the right, the right....
  selectPeg(cx+1, cy);
}


//move the selection left a column
void
TrianglePuzzle::left()
{
  //to the left, the left...
  selectPeg(cx-1, cy);
}


//perform a part of a move.  Returns true if valid, false if invalid
bool
TrianglePuzzle::move()
{
  int dx, dy;
  int midx, midy;
  int sx, sy;
  
  //handle the first selection
  if(mx == -1) {
    //can't select holes, only pegs
    if(!pegs[cy][cx]->isOccupied()) return false;
    
    //select the peg!
    mx = cx;
    my = cy;
    pegs[my][mx]->color(red);
    pegs[my][mx]->display();
    return true;
  }

  //ok, so it's the second selection! First, let's turn off the highlighting
  pegs[my][mx]->color(normal);
  pegs[my][mx]->display();

  //get the starting point
  sx = mx;
  sy = my;

  //reset move state
  my=mx=-1;

  
  //'now, let's check to see if the user is playing fair
  if(pegs[cy][cx]->isOccupied()) return false;  //this means that it's not a blank square

  //midpoints and distances
  midx = (cx+sx)/2;
  midy = (cy+sy)/2;
  dx = cx - sx;
  dy = cy - sy;
  if(dx<0) dx *= -1;
  if(dy<0) dy *= -1;
  

  //validate same row moves
  if(dy == 0 && dx != 2) return false;

  //validate different row moves
  if(dy != 0 && dy != 2) return false;
  if(dx != 2 && dx != 0) return false;

  //validate that we are skipping a peg
  if(!pegs[midy][midx]->isOccupied()) return false;



  //HUZZAH!  make the move!
  pegs[sy][sx]->take();
  pegs[cy][cx]->place();
  pegs[midy][midx]->take();

  return true;
}


void
TrianglePuzzle::reset()
{
  for(int y=0; y<pegs.size(); y++) {
    for(int x=0; x<pegs[y].size(); x++) {
      //the first row is empty, all others are taken
      if(y==0) {
        pegs[y][x]->take();
      } else {
	pegs[y][x]->place();
      }
    }
  }
}
@