![Børre Stenseth](http://www.it.hiof.no/~borres/allround/selfimages/bs.gif)
? Browser Support ?
HTML
>
Canvas
>
Processing
>Magi
Magiske kvadrater
Du skal bytte om de fargede rutene helt til alle kolonner og alle rader har samme sum.
Sørg for at processing sketchen har fokus(klikk på den) før du taster 'n' for nytt brett.
Det er to pde-filer som beskriver sketchen.
_magi.pde
/* Magic squares Code is taken from old, no processing applet and is modified as litle as possible */ final int sqdim=50; final int fontsize=20; int vals[]; int target[]; int hitx=-1; int hity=-1; int hitindex=-1; PFont bigF; PFont smallF; void setup(){ size(sqdim*7,sqdim*8); setupSquares(); bigF=createFont("Arial",fontsize); smallF=createFont("Arial",14); textFont(bigF); textAlign(CENTER,CENTER); } void setupSquares(){ target=new int[25]; // what we want to achieve vals=new int[25]; // what we have at the moment for(int ix=0;ix<25;ix++) vals[ix]=0; // pick a random solution int select=(int)(Math.random()*1000)%6; switch(select) { case 1: vals[0]=4; vals[1]=5; vals[2]=12; vals[3]=13; vals[5]=14; vals[6]=3; vals[7]=9; vals[8]=8; vals[10]=15; vals[11]=10; vals[12]=2; vals[13]=7; vals[15]=1; vals[16]=16; vals[17]=11; vals[18]=6; break; case 2: vals[0]=1; vals[1]=8; vals[2]=9; vals[3]=16; vals[5]=15; vals[6]=3; vals[7]=14; vals[8]=2; vals[10]=12; vals[11]=13; vals[12]=4; vals[13]=5; vals[15]=6; vals[16]=10; vals[17]=7; vals[18]=11; break; case 3: vals[0]=4; vals[1]=5; vals[2]=10; vals[3]=15; vals[5]=8; vals[6]=12; vals[7]=11; vals[8]=3; vals[10]=9; vals[11]=16; vals[12]=7; vals[13]=2; vals[15]=13; vals[16]=1; vals[17]=6; vals[18]=14; break; case 4: vals[0]=4; vals[1]=8; vals[2]=9; vals[3]=13; vals[5]=14; vals[6]=3; vals[7]=7; vals[8]=10; vals[10]=15; vals[11]=11; vals[12]=2; vals[13]=6; vals[15]=1; vals[16]=12; vals[17]=16; vals[18]=5; break; case 5: vals[0]=1; vals[1]=8; vals[2]=10; vals[3]=15; vals[5]=16; vals[6]=13; vals[7]=3; vals[8]=2; vals[10]=11; vals[11]=4; vals[12]=14; vals[13]=5; vals[15]=6; vals[16]=9; vals[17]=7; vals[18]=12; break; case 6: vals[0]=1; vals[1]=8; vals[2]=14; vals[3]=11; vals[5]=16; vals[6]=2; vals[7]=3; vals[8]=13; vals[10]=10; vals[11]=15; vals[12]=5; vals[13]=4; vals[15]=7; vals[16]=9; vals[17]=12; vals[18]=6; break; default: vals[0]=4; vals[1]=9; vals[2]=10; vals[3]=11; vals[5]=3; vals[6]=8; vals[7]=7; vals[8]=16; vals[10]=14; vals[11]=2; vals[12]=12; vals[13]=6; vals[15]=13; vals[16]=15; vals[17]=5; vals[18]=1; } // store the solution we want as target for(int ix=0;ix<25;ix++) target[ix]=vals[ix]; // do a random shuffle while(recalculateSquares()) { int swaps=(int)(Math.random()*1000)%12; for(int ix=0;ix<swaps;ix++) { int ind1=4; int ind2=4; while((ind1==4)||(ind1==9)||(ind1==14)) ind1=(int)(Math.random()*1000)%18; while((ind2==4)||(ind2==9)||(ind2==14)) ind2=(int)(Math.random()*1000)%18; swapVals(ind1,ind2); } } } boolean recalculateSquares() { // do sums vals[4]=vals[0]+vals[1]+vals[2]+vals[3]; vals[9]=vals[5]+vals[6]+vals[7]+vals[8]; vals[14]=vals[10]+vals[11]+vals[12]+vals[13]; vals[19]=vals[15]+vals[16]+vals[17]+vals[18]; vals[20]=vals[0]+vals[5]+vals[10]+vals[15]; vals[21]=vals[1]+vals[6]+vals[11]+vals[16]; vals[22]=vals[2]+vals[7]+vals[12]+vals[17]; vals[23]=vals[3]+vals[8]+vals[13]+vals[18]; //return true if all sum values are 34 if( (vals[4]==34) && (vals[9]==34) && (vals[14]==34) && (vals[19]==34) && (vals[20]==34) && (vals[21]==34) && (vals[22]==34) && (vals[23]==34) ) { for(int ix=0;ix<25;ix++) target[ix]=vals[ix]; return true; } return false; } void swapVals(int ix1,int ix2) { int tmp=vals[ix1]; vals[ix1]=vals[ix2]; vals[ix2]=tmp; } void setHitSquare(int mx, int my) { // mouse has hit at mx,my - is it a square int x,y; Rectangle r; hitx=-1; hity=-1; hitindex=-1; for(y=0;y<4;y++) for(x=0;x<4;x++) { int v=vals[getIndex(x,y)]; int t=target[getIndex(x,y)]; // modifyed to y+1 since we use one sqdim for top text r=new Rectangle((x+1)*sqdim,(y+1)*sqdim,sqdim,sqdim); if(r.contains(mx,my)) { if(t!=v) { hitx=x; hity=y; hitindex=getIndex(hitx,hity); return; } return; } } } int getIndex(int x, int y) { if((x>5)||(x<0)) return -1; if((y>5)||(y<0)) return -1; return y*5+x; } void draw() { background(200); if(recalculateSquares()) { fill(255,0,0); text("Flott, problemet løst",width/2,sqdim/2); } else{ textFont(smallF); fill(0); text("Alle rader og kolonner skal ha samme sum",width/2,sqdim/2); textFont(bigF); } // paint all the 25 fields according to status // note that we do a translate // to compensate for top text int x,y; pushMatrix(); translate(0,sqdim); for(y=0;y<5;y++) for(x=0;x<5;x++) { int v=vals[getIndex(x,y)]; int t=target[getIndex(x,y)]; if((x==4)&&(y==4)) { //drawSquare(g,(x+1)*sqdim,(y+1)*sqdim,v,3); } else if(x==4) { drawSquare((x+1)*sqdim+sqdim/2,(y)*sqdim,v,3); } else if(y==4) { drawSquare((x+1)*sqdim,(y)*sqdim+sqdim/2,v,3); } else if((x==hitx) &&(y==hity)) drawSquare((x+1)*sqdim,(y)*sqdim,v,2); else if(t==v) drawSquare((x+1)*sqdim,(y)*sqdim,v,0); else drawSquare((x+1)*sqdim,(y)*sqdim,v,1); } // draw the lines to isolate sums line(sqdim,4*sqdim+sqdim/3,6*sqdim+sqdim/2,4*sqdim+sqdim/3); line(5*sqdim+sqdim/3,0,5*sqdim+sqdim/3,5*sqdim+sqdim/2); // new board message textSize(14); smooth(); textFont(smallF); text("Klikk på to fargede ruter for å få dem til å bytte plass\n(tast 'n' for nytt brett)",width/2,sqdim*6.5); textFont(bigF); popMatrix(); } public void drawSquare(int lft,int tp,int val,int status) { switch(status) { case 0:// correctly placed within movables fill(255); break; case 1:// ucorrectly placed within movables fill(0); rect(lft,tp,sqdim,sqdim); fill(100,100,197); break; case 2:// ucorrectly placed within movables and hit as first fill(0); rect(lft,tp,sqdim,sqdim); fill(255,0,0); break; case 3:// sum fill(255); rect(lft,tp,sqdim,sqdim); break; default: ; }//switch rect(lft+1,tp+1,sqdim-1,sqdim-1); if(status==3) stroke(100); else stroke(0); rect(lft+1,tp+1,sqdim-1,sqdim-1); fill(0); text(val,lft+sqdim/2,tp+3*fontsize/2); } void mousePressed() { int oldhitx=-1; int oldhity=-1; // which have we hit if(hitx>=0) { oldhitx=hitx; oldhity=hity; } setHitSquare(mouseX,mouseY); if(hitx>=0) { if(oldhitx>=0) { int oldindex=getIndex(oldhitx,oldhity); int newindex=getIndex(hitx,hity); if(newindex!=oldindex) swapVals(oldindex,newindex); hitx=-1; hity=-1; } } } void keyPressed(){ if(key=='n' || key=='N') setupSquares(); }
og
_Rectangle.pde
class Rectangle{ float L; float T; float W; float H; Rectangle(float L,float T,float W,float H){ this.L=L; this.T=T; this.W=W; this.H=H; } boolean contains(float x, float y){ return x > L && x < L+W && y > T && y< T+H; } }
Den originale Appleten er slik:
_magiApp.java
import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.Label; import java.awt.Button; /** * Title: * Description: * Copyright: Copyright (c) 2001 * Company: * @author * @version 1.0 */ public class magiApp extends Applet implements ActionListener { private MyCanvas canvas; private MouseHandler mHandler; Label msg; Button go; // own final int sqdim=50; final int fontsize=20; int vals[]; int target[]; int hitx=-1; int hity=-1; int hitindex=-1; public void init() { setLayout( new BorderLayout() ); canvas = new MyCanvas(); canvas.setBackground( new Color( 255, 255, 255 ) ); canvas.setFont(new java.awt.Font("SansSerif", 1, fontsize)); msg=new Label(""); msg.setFont(new java.awt.Font("SansSerif", 1, fontsize)); msg.setBounds(sqdim,0,200,20); msg.setForeground(Color.red); msg.setBackground( new Color( 255, 255, 255 ) ); go=new Button("New board"); go.setBounds(0,0,sqdim,20); go.setFont(new java.awt.Font("SansSerif", 1, 12)); go.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { go_actionPerformed(e); } }); add( canvas, BorderLayout.CENTER ); add( msg,BorderLayout.NORTH); add( go,BorderLayout.SOUTH); mHandler = new MouseHandler(); canvas.addMouseListener( mHandler ); setupSquares(); } public void setupSquares() { target=new int[25]; // what we want to achieve vals=new int[25]; // what we have at the moment for(int ix=0;ix<25;ix++) vals[ix]=0; // pick a random solution int select=(int)(Math.random()*1000)%6; switch(select) { case 1: vals[0]=4; vals[1]=5; vals[2]=12; vals[3]=13; vals[5]=14; vals[6]=3; vals[7]=9; vals[8]=8; vals[10]=15; vals[11]=10; vals[12]=2; vals[13]=7; vals[15]=1; vals[16]=16; vals[17]=11; vals[18]=6; break; case 2: vals[0]=1; vals[1]=8; vals[2]=9; vals[3]=16; vals[5]=15; vals[6]=3; vals[7]=14; vals[8]=2; vals[10]=12; vals[11]=13; vals[12]=4; vals[13]=5; vals[15]=6; vals[16]=10; vals[17]=7; vals[18]=11; break; case 3: vals[0]=4; vals[1]=5; vals[2]=10; vals[3]=15; vals[5]=8; vals[6]=12; vals[7]=11; vals[8]=3; vals[10]=9; vals[11]=16; vals[12]=7; vals[13]=2; vals[15]=13; vals[16]=1; vals[17]=6; vals[18]=14; break; case 4: vals[0]=4; vals[1]=8; vals[2]=9; vals[3]=13; vals[5]=14; vals[6]=3; vals[7]=7; vals[8]=10; vals[10]=15; vals[11]=11; vals[12]=2; vals[13]=6; vals[15]=1; vals[16]=12; vals[17]=16; vals[18]=5; break; case 5: vals[0]=1; vals[1]=8; vals[2]=10; vals[3]=15; vals[5]=16; vals[6]=13; vals[7]=3; vals[8]=2; vals[10]=11; vals[11]=4; vals[12]=14; vals[13]=5; vals[15]=6; vals[16]=9; vals[17]=7; vals[18]=12; break; case 6: vals[0]=1; vals[1]=8; vals[2]=14; vals[3]=11; vals[5]=16; vals[6]=2; vals[7]=3; vals[8]=13; vals[10]=10; vals[11]=15; vals[12]=5; vals[13]=4; vals[15]=7; vals[16]=9; vals[17]=12; vals[18]=6; break; default: vals[0]=4; vals[1]=9; vals[2]=10; vals[3]=11; vals[5]=3; vals[6]=8; vals[7]=7; vals[8]=16; vals[10]=14; vals[11]=2; vals[12]=12; vals[13]=6; vals[15]=13; vals[16]=15; vals[17]=5; vals[18]=1; } // store the solution we want for(int ix=0;ix<25;ix++) target[ix]=vals[ix]; // do a random shuffle while(recalculateSquares()) { int swaps=(int)(Math.random()*1000)%12; for(int ix=0;ix<swaps;ix++) { int ind1=4; int ind2=4; while((ind1==4)||(ind1==9)||(ind1==14)) ind1=(int)(Math.random()*1000)%18; while((ind2==4)||(ind2==9)||(ind2==14)) ind2=(int)(Math.random()*1000)%18; swapVals(ind1,ind2); } } } public boolean recalculateSquares() { // do sums vals[4]=vals[0]+vals[1]+vals[2]+vals[3]; vals[9]=vals[5]+vals[6]+vals[7]+vals[8]; vals[14]=vals[10]+vals[11]+vals[12]+vals[13]; vals[19]=vals[15]+vals[16]+vals[17]+vals[18]; vals[20]=vals[0]+vals[5]+vals[10]+vals[15]; vals[21]=vals[1]+vals[6]+vals[11]+vals[16]; vals[22]=vals[2]+vals[7]+vals[12]+vals[17]; vals[23]=vals[3]+vals[8]+vals[13]+vals[18]; //return true if all sum values are 34 if( (vals[4]==34) && (vals[9]==34) && (vals[14]==34) && (vals[19]==34) && (vals[20]==34) && (vals[21]==34) && (vals[22]==34) && (vals[23]==34) ) { for(int ix=0;ix<25;ix++) target[ix]=vals[ix]; return true; } return false; } public void setHitSquare(int mx, int my) { // mouse has hit at mx,my - is it a square int x,y; Rectangle r; hitx=-1; hity=-1; hitindex=-1; for(y=0;y<4;y++) for(x=0;x<4;x++) { int v=vals[getIndex(x,y)]; int t=target[getIndex(x,y)]; r=new Rectangle((x+1)*sqdim,(y)*sqdim,sqdim,sqdim); if(r.contains(mx,my)) { if(t!=v) { hitx=x; hity=y; hitindex=getIndex(hitx,hity); return; } return; } } } public int getIndex(int x, int y) { if((x>5)||(x<0)) return -1; if((y>5)||(y<0)) return -1; return y*5+x; } public void swapVals(int ix1,int ix2) { int tmp=vals[ix1]; vals[ix1]=vals[ix2]; vals[ix2]=tmp; } public void actionPerformed( ActionEvent e ) { canvas.repaint(); } void go_actionPerformed(ActionEvent e) { setupSquares(); canvas.repaint(); } //internal class to handle mouse moves class MouseHandler implements MouseListener //, MouseMotionListener { public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { int oldhitx=-1; int oldhity=-1; // which have we hit if(hitx>=0) { oldhitx=hitx; oldhity=hity; } setHitSquare(e.getX(),e.getY()); if(hitx>=0) { if(oldhitx>=0) { int oldindex=getIndex(oldhitx,oldhity); int newindex=getIndex(hitx,hity); if(newindex!=oldindex) swapVals(oldindex,newindex); hitx=-1; hity=-1; } } canvas.repaint(); } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } }// mousehandler class MyCanvas extends Canvas { public void paint(Graphics g) { if(recalculateSquares()) { // problem is solved msg.setText(" Gratulations, problem solved"); } else msg.setText(" "); super.paint( g); // paint all the 25 fields according to status int x,y; for(y=0;y<5;y++) for(x=0;x<5;x++) { int v=vals[getIndex(x,y)]; int t=target[getIndex(x,y)]; if((x==4)&&(y==4)) { //drawSquare(g,(x+1)*sqdim,(y+1)*sqdim,v,3); } else if(x==4) { drawSquare(g,(x+1)*sqdim+sqdim/2,(y)*sqdim,v,3); } else if(y==4) { drawSquare(g,(x+1)*sqdim,(y)*sqdim+sqdim/2,v,3); } else if((x==hitx) &&(y==hity)) drawSquare(g,(x+1)*sqdim,(y)*sqdim,v,2); else if(t==v) drawSquare(g,(x+1)*sqdim,(y)*sqdim,v,0); else drawSquare(g,(x+1)*sqdim,(y)*sqdim,v,1); } // draw the lines to isolate sums g.drawLine(sqdim,4*sqdim+sqdim/3,6*sqdim+sqdim/2,4*sqdim+sqdim/3); g.drawLine(5*sqdim+sqdim/3,0,5*sqdim+sqdim/3,5*sqdim+sqdim/2); } public void drawSquare(Graphics g,int lft,int tp,int val,int status) { switch(status) { case 0:// correctly placed within movables g.setColor(Color.white); break; case 1:// ucorrectly placed within movables g.setColor(Color.black); g.drawRect(lft,tp,sqdim,sqdim); g.setColor(new Color(100,100,197)); break; case 2:// ucorrectly placed within movables and hit as first g.setColor(Color.black); g.drawRect(lft,tp,sqdim,sqdim); g.setColor(Color.red); break; case 3:// sum g.setColor(Color.white); g.drawRect(lft,tp,sqdim,sqdim); break; default: ; }//switch g.fillRect(lft+1,tp+1,sqdim-1,sqdim-1); if(status==3) g.setColor(Color.gray); else g.setColor(Color.black); g.drawString(new Integer(val).toString(),lft+sqdim/2-fontsize/2,tp+3*fontsize/2); } }// MyCanvas }